|
Post by n00b on Mar 20, 2021 0:47:28 GMT -6
I guess you were able to find a way to solve that problem. It was very difficult for me to find a work around within the limitations of Micro(A) but if it can solve that problem it would probably be able to solve most others.
|
|
|
Post by johnno56 on Jun 18, 2021 9:08:05 GMT -6
Hi Aurel,
Hmm... Easiest?
Collision detection can get a little tricky. Most Basics will use algorithms to figure it out. Some Basics have collision detection "built in".
The three "simplest" collision detection routines that I use are: Rectangle and Rectangle (AABB - Axis Aligned Bounding Box); Rectangle and Circle; Circle and Circle.
AABB: If the "boundaries" of one rectagle "overlaps" the "boundaries" of the second rectangle - collision
xmax = 640 ymax = 480 title$ = "Axial Aligned Bounding Box Collision"
WindowOpen(1,title$,0,0,xmax,ymax,0) CanvasOpen(1,xmax,ymax,0,0,xmax,ymax,0)
collision = 0
'==================================================== ' ' Axial Aligned Bounding Box Collision Detection ' FUNCTION collide (box1bottom, box1top, box1left, box1right, box2bottom, box2top, box2left, box2right) IF (box1bottom < box2top) OR (box1top > box2bottom) OR (box1left > box2right) OR (box1right < box2left) THEN collision = 0 ELSE collision = 1 END IF RETURN collision END FUNCTION '====================================================
box1top = 190 box1bottom = 290 box1left = 270 box1right = 370
DO clearcanvas
mx = MOUSEX() my = MOUSEY()
box2left = mx - 50 box2top = my - 50 box2right = mx + 50 box2bottom = my + 50
SETCOLOR(RGB(255, 128, 0)) BOX(box2left, box2top, box2right, box2bottom)
IF collide(box1bottom, box1top, box1left, box1right, box2bottom, box2top, box2left, box2right) = 1 THEN SETCOLOR(RGB(255, 255, 0)) BOXFILL(box1left, box1top, box1right, box1bottom) SETCOLOR(RGB(255, 128, 0)) BOXFILL(box2left, box2top, box2right, box2bottom) ELSE SETCOLOR(RGB(255, 255, 0)) BOX(box1left, box1top, box1right, box1bottom) SETCOLOR(RGB(255, 128, 0)) BOX(box2left, box2top, box2right, box2bottom) END IF
UPDATE() LOOP UNTIL key(27) = 1 CLEARCANVAS END RECTANGLE and CIRCLE: If the centre of the circle plus its radius "overlaps" the "boundaries" of the rectangle - collision
xmax = 640 ymax = 480 title$ = "Circle Rectangle Collision"
WindowOpen(1,title$,0,0,xmax,ymax,0) CanvasOpen(1,xmax,ymax,0,0,xmax,ymax,0)
function collide(cx,cy,radius,rx,ry,rw,rh) distX = abs(cx - rx - rw / 2) distY = abs(cy - ry - rh / 2) if distX > (rw / 2 + radius) then return false end if if distY > (rh / 2 + radius) then return false end if if distX <= rw / 2 then return true end if if distY < rh / 2 then return true end if
dx = distX - rw / 2 dy = distY - rh / 2
return (dx * dx + dy * dy <= (radius * radius)) end function
radius = 30 rx = 220 ry = 140 rw = 200 rh = 200
do clearcanvas cx = mousex cy = mousey if collide(cx,cy,radius,rx,ry,rw,rh) then setColor(rgb(0,0,255)) RectFill(rx,ry,rw,rh) else setColor(rgb(255,128,0)) RectFill(rx,ry,rw,rh) end if setColor(rgb(128,128,128)) circleFill(cx,cy,radius) update() loop until key(k_escape) = 1 CIRCLE AND CIRCLE: If the distance between the two circles is less than the sum of the radii - collision
xmax = 640 ymax = 480 title$ = "Circular Collision"
WindowOpen(1,title$,0,0,xmax,ymax,0) CanvasOpen(1,xmax,ymax,0,0,xmax,ymax,0)
' circ1 x/y centre of circle 1 ' circ2 x/y center of circle 2 ' r1 radius of circle 1 ' r2 radius of circle 2
collision = 0
function collide(circ1x, circ1y, circ2x, circ2y, r1, r2) ' Calculate difference between centres distX = circ1x - circ2x distY = circ1y - circ2y ' Get distance using Pythagoras dist = sqrt((distX * distX) + (distY * distY)) if dist <= (r1 + r2) then collision = 1 else collision = 0 end if return collision end function
circ1x = 320 circ1y = 240 r1 = 100
r2 = 50
distX =0 distY =0 dist = 0
do circ2x = mousex() circ2y = mousey() ClearCanvas
collision = collide(circ1x, circ1y, circ2x, circ2y, r1, r2) if collision = 1 then setColor(rgb(255,255,0)) circlefill(circ1x, circ1y, r1) setColor(rgb(255,128,0)) circlefill(circ2x, circ2y, r2) else setColor(rgb(255,255,0)) circle(circ1x, circ1y, r1) setColor(rgb(255,128,0)) circle(circ2x, circ2y, r2) end if
update() loop until key(k_escape) = 1
I hope that these routines will be helpful...
J
|
|
|
Post by johnno56 on Jun 18, 2021 21:14:51 GMT -6
I suppose the "easiest" collision detection would be the 'Circle and Circle'. If you look at it, all it is doing, is keeping track of two points. The centres of each circle... Whereas the 'AABB' keeps track of 16 points... The beginning and end of each of the 8 boundaries. 4 boundaries per rectangle. It's a numbers game... lol
|
|
|
Post by aurel on Jun 21, 2021 6:55:59 GMT -6
And i finally made working graphical GDI aka ...space Shooter anyone maybe want to try ? Collision is made by rectangle method ..i think 'test demo in gdi ptr img,img2,img3,img4 ptr wmKeyDown, wmTimer var wp,ix,iy,p,ex,ey,eh,ev,xx,yy,score,bx,by,bf,hit wcolor 200,200,210 fcolor 180,60,150 : print 10,510,"Simple shooter" LoadImg img,"nebula1.bmp",0,640,400,16 'program name... print 10,440,"Space Mines m(A)": print 10,460,"Press ESC for pause.." 'show img on window ShowImgT img,0,0,640,360 'load another image LoadImg img2,"ship1.bmp" , 0, 32, 32,16 LoadImg img3,"mine1.bmp" , 0, 32, 32,24 LoadImg img4,"rocket.bmp" , 0, 32, 32,16 ShowImgT img3,300, 300, 32, 32 ex = 300 : ey = 30 : ix = 300 : iy = 360 updateScreen() 'show score rect fcolor 80,80,100 :rect 524,470,68,24 fcolor 245,118,0 : print 530,475,score
'events... WinMsg wmKEYDOWN
hWparam wp 'vkLEFT ----------------------------------- if wp = 37 if ix > 0 :ix = ix - 2 : endif endif
'vkRIGHT ?---------------------------------- if wp = 39 if ix < 600 : ix = ix + 2 : endif endif
'vkUP -------------------------------------- if wp = 38 if iy > 0 : iy = iy - 2 :endif endif
'vkDOWN -------------------------------------- if wp = 40 if iy < 360 : iy = iy + 2 :endif endif
'vkSPACE if wp =32 if bf = 0 bf = 1 bx = ix by = iy endif endif
'game loop if key not ESC while wp ! 27 hit=0 updateBack() updateScreen() updateBullet() updateEnemy() updateShip() testCollision() 'delay loop ' p=0 ' while p < 800 ' p=p+0.01
swap 'ShowImg img,0,0,646,438 wend
EndWm
func updateScreen() fcolor 80,80,100 : rect 524,415,68,24 fcolor 100,160,220 : print 530,420,ix
fcolor 80,80,100 : rect 524,440,68,24 fcolor 100,160,220 : print 530,445,iy
'Display bullet if bf = 1 ShowImgT img4, bx, by, 32, 32 'update by bullet position endif
'show enemy ShowImgT img3, ex, ey, 32, 32 'show ship ShowImgT img2,ix,iy,32,32
'update score fcolor 80,80,100 :rect 524,470,68,24 fcolor 245,118,0 : print 530,475,score 'swap endfn
func updateBack() ShowImgT img,0,0,640,400 endFn
func updateShip() ShowImgT img2,ix,iy,32,32 endFn
func updateBullet() if bf = 1 by = by - 1 'Bullet has left the screen. if by < 0 : bf=0 : endif endif endfn
func updateEnemy() if ex < 600 : ex = ex + 1 : endif if ex = 598 : ex = 10 : endif eh=ex+32 : ev=ey+32 endfn
func testCollision()
if bx > ex & bx < eh if by > ey & by < ev hit = 1 endif else hit = 0 endif
if hit = 1 fcolor 220,100,100: print ex,ey,"-XX-" score = score + 1 endif endfn
|
|
|
Post by aurel on Sept 8, 2022 13:25:14 GMT -6
i still have problem with game mechanic and collision * ouch...games are not for me maybe i should study ZX basic games again???
|
|