@RonJeffries I was playing around with the shield hits by the missiles and I came up with this code. Instead of using the actual shield sprites, I just used plain white rectangles. That way nobody has to get the shield sprites to try this code. Just tap the screen multiple times near the bottom or top to shoot the missiles. This still needs some work, but this is just an example.
@RonJeffries Heres another version of the shield hits. This shows two options. One is the original random hit within a rectangle. The other is a full hit within a circle. Slide the circ parameter to switch between them. The size of the hit circle can be changed by setting rad in the last function. You can shoot from below or above.
displayMode(STANDARD)
function setup()
parameter.boolean("circ",false)
fill(255,0,0)
rectMode(CENTER)
spriteMode(CENTER)
missileWidth=10
missileHeight=20
missileTab={}
shieldTab={}
shieldImg={}
for s=1,5 do
shieldImg[s]=image(88,64)
setContext(shieldImg[s])
background(255)
setContext()
shieldTab[s]=shields(shieldImg[s],vec2(180*s,HEIGHT/2),88,64)
end
end
function draw()
background(0)
text("tap multiple times near the bottom or top",WIDTH/2,100)
for a,b in pairs(missileTab) do
rect(b.mx,b.my,missileWidth,missileHeight)
b.my=b.my+b.mv
if b.my>HEIGHT or b.my<0 then
table.remove(missileTab,a)
end
end
for s=1,#shieldTab do
shieldTab[s]:draw()
end
end
function touched(t)
if t.state==BEGAN then
v=5
if t.y>HEIGHT/2 then
v=-5
end
table.insert(missileTab,{mx=t.x,my=t.y,mv=v})
end
end
shields=class()
function shields:init(shld,pos,sw,sh)
self.shield=shld
self.center=pos
self.width=sw
self.height=sh
self.left=self.center.x-self.width/2
self.right=self.center.x+self.width/2
self.bottom=self.center.y-self.height/2
self.top=self.center.y+self.height/2
self.withinRange=false
self.hit=false
end
function shields:draw()
sprite(self.shield,self.center.x,self.center.y)
for a,b in pairs(missileTab) do
self:shieldRange(b)
self:shieldHit(b)
if circ then
self:shieldExplodeCirc(a,b)
else
self:shieldExplodeRec(a,b)
end
end
end
function shields:shieldRange(b)
if b.mx+missileWidth/2>=self.left and
b.mx-missileWidth/2<=self.right and
b.my+missileHeight/2>self.bottom and
b.my-missileHeight/2<self.top then
self.withinRange=true
end
end
function shields:shieldHit(b)
if self.withinRange then
for x=-missileWidth/2,missileWidth/2 do
for y=-missileHeight/2,missileHeight/2 do
xx=(b.mx-(self.left)+x)//1
yy=(b.my-(self.bottom)+y)//1
if xx>=1 and xx<=self.width and yy>=1 and yy<=self.height then
r1,g1,b1=self.shield:get(xx,yy)
if r1+g1+b1>0 then
self.hit=true
self.withinRange=false
return
end
end
end
end
end
end
function shields:shieldExplodeRec(a,b)
if self.hit then
for x=-missileWidth,missileWidth do
for y=1,15 do
for z=1,15 do
a1=math.random(-15,15)
b1=math.random(25)
if b.mv<0 then
b1=-b1-missileHeight/2
end
self.shield:set((b.mx-self.left+x+a1)//1,
(b.my-self.bottom+y+b1)//1,0,0,0,0)
end
end
end
self.hit=false
table.remove(missileTab,a)
end
end
function shields:shieldExplodeCirc(a,b)
if self.hit then
local rad=15
local t=rad
if b.mv<0 then
t=-rad
end
xx=b.mx-self.left
yy=b.my-self.bottom+t
for xx1=-rad,rad do
for yy1=-rad,yy+rad do
if xx1^2+yy1^2<rad^2 then
self.shield:set((xx1+xx)//1,(yy1+yy)//1,0,0,0,0)
end
end
end
self.hit=false
table.remove(missileTab,a)
end
end
the random one is nicer, isn't it? i was a bit surprised at the way you handled the sequential in-range, actually hit, ok explode logic. interesting, i'll have to think about it to decide how i feel.
@RonJeffries I wanted to make sure the missile was within the bitmap area before I started checking anything. Then when it was within a bitmap range, I checked for any bit overlapped by the missile. As soon as I detected an overlap, I set the explode flag and exited the routine. That way I didn’t spend a lot of time over checking for bit map missile overlaps. I was looking for the first one before calling explode.
I also liked the random explode, but I wanted to see what a circular explode looked like. Maybe a random explode within a circular area instead of the rectangular area.
yes ... i'd more likely have cascaded the checks or anded them or something. it was an interesting approach that i want to think about. the original game, i think, actually erases just where the missile hits. i'll have to study the code to be sure. for a similar look, i'm thinking the more rectangular explosion is better. not sure yet, tho. thanks!
@RonJeffries Just read your latest article where you talked about my code. I found it interesting how you would do things different. By returning true or false from some functions eliminated setting and clearing some variables. Also, the way you check a variable at the start of a function and return immediately instead of putting code within an if statement. I read your articles each time you post something just to see your approach at coding. When I was watching the video when there was a slew of missiles coming down, I noticed some of the missiles were disappearing before they hit anything. That might be caused by the way I’m deleting the missiles. Tables should be traversed in reverse order if things are being shown and deleted in the same for loop. I didn’t think there would be that many missiles at one time.
PS. I just realized that we live about 150 miles apart. I’m between Toledo and Cleveland.
neighbors, neat! yes, object deletion is tricky. backward should help. i enjoy considering different ways of expressing things and am glad you read my stuff!
@RonJeffries Read your latest article, #16. I kind of look forward to what you have to say and seeing how you build up your code. I thought I’d pull out some code I had about moving invaders. Keep tapping the screen to randomly kill an invader which causes their speed to increase. It’s interesting to see how different our coding styles are. You code more professionally while I just kind of hack stuff to work.
displayMode(FULLSCREEN)
function setup()
rectMode(CENTER)
inv=Invaders()
end
function draw()
background(0)
inv:draw()
end
function touched(t)
inv:touched(t)
end
Invaders=class()
function Invaders:init()
self.cnt=0
self.delay=0
self.rev=false
self.incX=20
self.decY=0
self.row=6
self.invTab={}
fill(255)
for y=1,5 do
self.invTab[y]={}
for x=1,11 do
local p=vec2(x*50,HEIGHT-50-y*50)
self.invTab[y][x]={pos=p,alive=true}
end
end
end
function Invaders:draw()
self.cnt=0
for y=1,5 do
for x=1,11 do
local i=self.invTab[y][x]
if i.alive then
self.cnt=self.cnt+1
sprite(asset.builtin.Space_Art.Part_Red_Hull_3,i.pos.x,i.pos.y,30)
end
end
end
self:update()
end
function Invaders:update()
if self:checkDelay() then
self.row=self.row-1
for x=1,11 do
local i=self.invTab[self.row][x]
i.pos.x=i.pos.x+self.incX
i.pos.y=i.pos.y-self.decY
if (i.pos.x<40 or i.pos.x>WIDTH-40) and i.alive then
self.rev=true
end
end
if self.row==1 then
self.row=6
self.delay=0
self.decY=0
if self.rev then
self.rev=false
self.incX=self.incX*-1
self.decY=20
end
end
end
end
function Invaders:checkDelay()
self.delay=self.delay+1
if self.delay>self.cnt/55*9 then
self.delay=0
return true
end
end
function Invaders:touched(t)
if t.state==BEGAN then
y=math.random(5)
x=math.random(11)
self.invTab[y][x].alive=false
end
end
nice. i'm not sure "professionally" is quite right, but i do want to explore and show how we can move from something small and hacked together, to something with enough good design to grow for a long time.
i often like the direct ways you do things. i've almost forgotten how to work that way.
Comments
@RonJeffries Sorry, I forgot to mention in the write up that the Shield image was 4x the normal size. I had that in the comments in the code.
looks pretty good, thanks!
@RonJeffries I was playing around with the shield hits by the missiles and I came up with this code. Instead of using the actual shield sprites, I just used plain white rectangles. That way nobody has to get the shield sprites to try this code. Just tap the screen multiple times near the bottom or top to shoot the missiles. This still needs some work, but this is just an example.
interesting and useful idea. surprised to find that out of range sets are ignored.
@RonJeffries Heres another version of the shield hits. This shows two options. One is the original random hit within a rectangle. The other is a full hit within a circle. Slide the circ parameter to switch between them. The size of the hit circle can be changed by setting rad in the last function. You can shoot from below or above.
Thanks, will check it out.
the random one is nicer, isn't it? i was a bit surprised at the way you handled the sequential in-range, actually hit, ok explode logic. interesting, i'll have to think about it to decide how i feel.
@RonJeffries I wanted to make sure the missile was within the bitmap area before I started checking anything. Then when it was within a bitmap range, I checked for any bit overlapped by the missile. As soon as I detected an overlap, I set the explode flag and exited the routine. That way I didn’t spend a lot of time over checking for bit map missile overlaps. I was looking for the first one before calling explode.
I also liked the random explode, but I wanted to see what a circular explode looked like. Maybe a random explode within a circular area instead of the rectangular area.
yes ... i'd more likely have cascaded the checks or anded them or something. it was an interesting approach that i want to think about. the original game, i think, actually erases just where the missile hits. i'll have to study the code to be sure. for a similar look, i'm thinking the more rectangular explosion is better. not sure yet, tho. thanks!
@RonJeffries Just read your latest article where you talked about my code. I found it interesting how you would do things different. By returning true or false from some functions eliminated setting and clearing some variables. Also, the way you check a variable at the start of a function and return immediately instead of putting code within an if statement. I read your articles each time you post something just to see your approach at coding. When I was watching the video when there was a slew of missiles coming down, I noticed some of the missiles were disappearing before they hit anything. That might be caused by the way I’m deleting the missiles. Tables should be traversed in reverse order if things are being shown and deleted in the same for loop. I didn’t think there would be that many missiles at one time.
PS. I just realized that we live about 150 miles apart. I’m between Toledo and Cleveland.
neighbors, neat! yes, object deletion is tricky. backward should help. i enjoy considering different ways of expressing things and am glad you read my stuff!
@RonJeffries Read your latest article, #16. I kind of look forward to what you have to say and seeing how you build up your code. I thought I’d pull out some code I had about moving invaders. Keep tapping the screen to randomly kill an invader which causes their speed to increase. It’s interesting to see how different our coding styles are. You code more professionally while I just kind of hack stuff to work.
nice. i'm not sure "professionally" is quite right, but i do want to explore and show how we can move from something small and hacked together, to something with enough good design to grow for a long time.
i often like the direct ways you do things. i've almost forgotten how to work that way.
thanks!