Checking fields and stuff with an array? Questions
BlitzMax Forums/BlitzMax Beginners Area/Checking fields and stuff with an array? Questions
| ||
I am trying to make a check between player bullets and any of the 10 cpu's i created. I have successfully made 10 separate cpu images on my screen, but it only registers a hit at the invisible spot of (20,20), let me explain.... Automidhandle is set to true, and i create the types for my player/cpu and bullets Type spaceship Field x:Int,y:Int,frame:Int Field health:Int = 100, shield:Int EndType Type bullettype Field x:Int Field y:Int = 560 Field yv:Int = 4 Field frame:Int Field sender:Int 'Who sent the bullet? 1 = player ; 0 = cpu Field status:Int 'Alive = 1 ; Dead = 0 EndType I create the types for the all of the things in my game... ' 'CREATE TYPES Global player:spaceship = New spaceship Global cpu:spaceship = New spaceship Global Cbullet:bullettype = New bullettype Global Pbullet:bullettype = New bullettype ' 'CREATE THE LISTS Global cpuList:TList = CreateList () 'List for cpu's Global CbulletList:TList = CreateList () 'List for computer bullets Global PbulletList:TList = CreateList () 'List for player bullets I have a very simple main loop, only 2 functions, Draw () and UserInput (). Update () is commented out while I figure out my program ' 'MAIN LOOP While Not KeyHit(ESC) Cls UserInput () Draw () 'Update () Flip Wend StartGame() is called before the main loop, this may be where my problem lies... I create the player at 400,550 and 10 cpu's at an x-value of 500 and a y-value at a rand of 10-400. I assume I added them to the list correctly, because they all display on my screen Function StartGame () player.x = 400 player.y = 550 For Local cpuNum:Int = 1 To 10 Local cpu:spaceship = New spaceship cpu.x = 500 cpu.y = Rand(10,400) ListAddLast(cpuList,cpu) Next End Function UserInput () just checks input of keys hit, I don't think anything is wrong here; BOTH player (Pbullet) and cpu (Cbullet) bullet's show up on screen. Function UserInput () ' 'PLAYER MOVEMENT If KeyDown(LEFTKEY) player.x:-playerspeed EndIf If KeyDown(RIGHTKEY) player.x:+playerspeed EndIf ' 'FIRING If KeyDown(SPACEBAR) Local Cbullet:bullettype = New bullettype Cbullet.x = Rand(0,770) Cbullet.y = 10 Cbullet.frame = 0 ListAddLast(CbulletList,Cbullet) EndIf If KeyDown(VKEY) Local Pbullet:bullettype = New bullettype Pbullet.x = player.x + 15 Pbullet.y = player.y + 10 ListAddLast(PbulletList,Pbullet) EndIf EndFunction Draw (), this is the function I have questions about: Function Draw () ' 'DRAW Cbullets For Local Cbullet:bullettype = EachIn CbulletList Cbullet.y:+ Cbullet.yv Cbullet.frame:+1 If Cbullet.frame > 3 Cbullet.frame = 0 EndIf DrawImage Cbulletimage:TImage,Cbullet.x,Cbullet.y,Cbullet.frame If Cbullet.y > 575 ListRemove (CbulletList,Cbullet) EndIf If ImagesCollide(Cbulletimage,Cbullet.x,Cbullet.y,0,playerimage,player.x,player.y,0) player.health:-1 ListRemove (CbulletList,Cbullet) EndIf Next The code above works perfectly. The y value of the bullets increases, the frames work good. If the bullet hits the boundry it is deleted. If the bullet hits the player it is deleted and the player.health decreases by one. ' 'DRAW Pbullets For Local Pbullet:bullettype = EachIn PbulletList Pbullet.y:- Pbullet.yv DrawImage Pbulletimage:TImage,Pbullet.x,Pbullet.y If Pbullet.y < 0 ListRemove (PbulletList,Pbullet) EndIf If ImagesCollide(Pbulletimage,Pbullet.x,Pbullet.y,0,cpuimage,cpu.x,cpu.y,0) cpu.health:-1 ListRemove (PbulletList,Pbullet) EndIf Next The player bullets DRAW, but they don't collide with any of the images of the cpu. Strangely, it DOES connect with a spot (about (20,20)) on the screen. I have a debug command that writes the cpu.health on screen and it decreases when bullets hit this spot (20,20). The bullets DO delete when hitting this spot... I have no idea why ' 'DRAW PLAYER If player.health > 0 DrawImage(playerimage:TImage,player.x,player.y) Else EndIf ' 'DRAW CPU For Local cpu:spaceship = EachIn cpuList If cpu.health > 0 DrawImage cpuimage:TImage,cpu.x,cpu.y Else EndIf Next And finally just drawing the player and cpu. THe player image will not be shown when player.health goes to 0, although I can still move the player. Is there a way to delete this type once health hits < 0? If you see a problem what I did, can you suggest what I should look at? (not directlly tell me the answer; it will help me ;D ) Thanks again BMax community!! |
| ||
I think the problem lies within this piece of code:' 'DRAW Pbullets For Local Pbullet:bullettype = EachIn PbulletList Pbullet.y:- Pbullet.yv DrawImage Pbulletimage:TImage,Pbullet.x,Pbullet.y If Pbullet.y < 0 ListRemove (PbulletList,Pbullet) EndIf If ImagesCollide(Pbulletimage,Pbullet.x,Pbullet.y,0,cpuimage,cpu.x,cpu.y,0) cpu.health:-1 ListRemove (PbulletList,Pbullet) EndIf Next The way I am reading this is that any instance of Pbullet that is created, if this collides with a cpu image then it will delete both. Since the cpu and Pbullet both can exist in more than one at a single instance, do you have to do something like this? ' 'DRAW Pbullets For Local Pbullet:bullettype = EachIn PbulletList For Local cpu:spaceship = EachIn cpuList 'ADDED this Pbullet.y:- Pbullet.yv DrawImage Pbulletimage:TImage,Pbullet.x,Pbullet.y If Pbullet.y < 0 ListRemove (PbulletList,Pbullet) EndIf If ImagesCollide(Pbulletimage,Pbullet.x,Pbullet.y,0,cpuimage,cpu.x,cpu.y,0) cpu.health:-1 ListRemove (PbulletList,Pbullet) EndIf Next Next 'ADDED this ? |
| ||
try keeping your draw and your processing separate: for example draw: function drawAll() for local cpu:spaceship eachin cpuList drawimage spaceshipImg,cpu.x,cpu.y,cpu.frame next for local pbullet:bullettype = eachin pbulletList DrawImage pbuletImage,pbullet.x,pbullet.y next end function and a function that does all of the processing that way you can keep your code a bit better organized there is a little problem with your logic for when you remove bullet first, if bullet y < 0 you delete the bullet but if it's deleted why are you checking for collision? second, once the bullet is stored in Pbullet it wont be deleted until the eachin assigns the next bullet to Pbullet and that won't happen until it goes through all of the spaceships. that means that if the bullet hits the first ship and you remove it from the list it still exists in the variable Pbullet so it still going to check for collision with the other spaceships. one way to avoid this is to exit the spaceship for loop after the bullet is deleted from the list with an exit. Last edited 2011 |
| ||
Since I am terribly inexperienced with programming can I ask as to clarify what you said? Using the For Local Pbullet:bullettype = Eachin PbulletList If ImagesCollide(Pbulletimage,Pbullet.x,Pbullet.y,0,cpuimage,cpu.x,cpu.y,0) Specifically the part: " ...cpuimage,cpu.x,cpu.y,0" Does this signify to the compiler to check for collision of the cpu as a whole (all instances of it) or each individual cpu created. The way I am understanding what you said, you said it is checking for collisions between all images? The exit function as well... The way I understand it (I may be wrong) but "For Local... Eachin TList" does an action for everything in this list correct? If I tell the compiler to create a bullet, and add it to the list when I hit a key. When I do this it should be added to a list correct? Should I be using ListAddFirst instead of ListAddLast? If I check for collisions in this list, if they occur I would delete them from the list and delete the bullet (I have no collision checks for bullets outside of the list) I am trying to understand what you are saying :) |
| ||
just to clarify the" eachin lists" only goes from the top of the list to the bottom. There is no going from the bottom to the top. what eachin does is, it start from the first object in the list and will continue grabbing objects. If the list contain bullets it will start grabbing from the top of the list one at a time and assign it to the local variable in this case the Pbullet. on your bullet "for loop" eachin will assign the first bullet to the variable Pbullet it will perform all of the actions inside the "For loop" and when it reaches next it will go back to the "for eachin" and will assign the next bullet in the list to "Pbullet" variable until the last bullet. that means that while inside the "for/next" loop the bullet will exist in the Pbullet variable unless you null the Pbullet. in your previos post you created the for next loop and you include the test for when a bullet goes out of view. then, you told it to delete the bullet from the list. the bullet is removed from the list but it is still in the variable "Pbullet". so just remember that the bullet got deleted from the list because it went out of side of view but you still performed the second test to see if it collided with the spaceship. you can do that but technically there is no reason for the test because you already deleted it from the list and it can not be deleted twice. in that case there is not reason for the test. the other problem was that you are using the bullet inside a nested for/next loop of spaceships. lets assume the bullet hits the first ship in the for loop. the way you have it, it will collide with the ship. you will remove it from the list, afterwards it will cycle through to the next ship and because it still exists in the Pbullet bariable it will check for collision and out of bound with the new spaceship. it will continue to do that until the last ship. what you need to do is exit the spaceship loop after either of the collisions. this is all you need to do: For Local Pbullet:bullettype = EachIn PbulletList For Local cpu:spaceship = EachIn cpuList 'ADDED this Pbullet.y:- Pbullet.yv DrawImage Pbulletimage:TImage,Pbullet.x,Pbullet.y If Pbullet.y < 0 ListRemove (PbulletList,Pbullet) Exit ' <----------this will exit the spaceship loop EndIf If ImagesCollide(Pbulletimage,Pbullet.x,Pbullet.y,0,cpuimage,cpu.x,cpu.y,0) cpu.health:-1 ListRemove (PbulletList,Pbullet) Exit ' <---------this will exit the spaceship loop EndIf Next Next 'ADDED this all you needed to do is add exit so that it will exit the inner for/next loop and continue with the next bullet. |
| ||
I understand now what you mean by: you created the for next loop and you include the test for when a bullet goes out of view. then, you told it to delete the bullet from the list. the bullet is removed from the list but it is still in the variable "Pbullet". so just remember that the bullet got deleted from the list because it went out of side of view but you still performed the second test to see if it collided with the spaceship. you can do that but technically there is no reason for the test because you already deleted it from the list and it can not be deleted twice. in that case there is not reason for the test. When you said: the other problem was that you are using the bullet inside a nested for/next loop of spaceships. and referring to: ' 'DRAW Pbullets For Local Pbullet:bullettype = EachIn PbulletList For Local cpu:spaceship = EachIn cpuList 'ADDED this Pbullet.y:- Pbullet.yv DrawImage Pbulletimage:TImage,Pbullet.x,Pbullet.y If Pbullet.y < 0 ListRemove (PbulletList,Pbullet) EndIf If ImagesCollide(Pbulletimage,Pbullet.x,Pbullet.y,0,cpuimage,cpu.x,cpu.y,0) cpu.health:-1 ListRemove (PbulletList,Pbullet) EndIf Next Next 'ADDED this This was actually a shot in the dark by me, I don't know if it would work or not. But when you suggested to add a Exit in here I tried it out and the bullets DO now delete when they hit any of the cpu images, but the cpu.health still remains a constant. I will worry about the health later and try to understand these changes to my code. I am thinking about re-coding this Pbullet to something like If .... y < 0 listremove exit Elseif images collide listremove cpu.health:-2 exit else draw bullet endif Frankly, I do not like the look of a for...next loop within another for...next loop, it looks too complicated but it DOES work... I would rather understand and have the code longer rather than some quick fix I don't understand :P thanks so far Jesse!! |
| ||
Is it the only way to check the bullet collision by having a For...Next (for Pbullets) and a For...Next (for cpu's) if I have more than once instance at a time? |
| ||
No. you can use repeat/until, while/wend etc. but its basically the same thing. you loop through each bullet and for each bullet you loop through each of the ships. Last edited 2011 |
| ||
? You just said you need to check for that ? "Loop through each bullet... loop through each ship" Then I will guess it IS the way to go to put a nested loop within my bullet loop for ships? |