Posted: Sat Apr 30, 2005 3:13 pm Post subject: Help with shooting
im working on an addition to my blockout game, when you press space, bullets shoot from the paddle, and i want them to destroy 1 block and then dissapear, and i want rapid fire.
I did this so far, but i'm not sure how to get more bullets going at the same time, right now when you press Space, 1 bullet goes, and when you press Space again, the bullet dissapears and another one shoots.
I think i have to do something with flexible arrays, but not quite sure what exactly.
Heres the code:
Turing:
type block : record
x :int
y :int
hits :int endrecord %type bulletvars : % record % x : int % y : int % hits : int % end record var xvalue :int:= -15 var yvalue :int:=0 var blocks :array1.. 156of block
var colours :array1.. 10ofint:=init(40, 50, 60, 70, 80, 90, 100, 110, 120, 130) var blockcol :array1.. 156ofint %var bullet : array 1 .. 100 of bulletvars var chars :arraycharofboolean var shoot :=true var ballx :=maxxdiv2 var bally :=15 var pos :=maxxdiv2 var xmod :=1 var ymod :=1 var tries :=3 var score :=0 var font3 :=Font.New("Courier New:10:bold")%All other font var keyPressed :string(1) var bulbutton :=chr(ORD_SPACE) var bulletx :int:=0 var bullety :int:=8 setscreen("graphics:640;400,title:Mikes X-Treme Pong Game,nocursor")
process bulletfire
loop % for x : 1 .. 50 Draw.FillOval(bulletx, bullety, 3, 3, 43)
bullety +=1 delay(40) % end for exitwhenwhatdotcolour(bulletx, bullety + 3)not= 0 endloop end bulletfire
for i :1.. upper(blocks)
blocks (i).hits :=0 endfor %for i : 1 .. upper (bullet) % bullet (i).x := pos % bullet (i).y := 10 % bullet (i).hits := 0 %end for
Posted: Sat Apr 30, 2005 8:44 pm Post subject: (No subject)
Yep, flexible arrays is the key here. Whenever you hit the fire button, you create a new element of the flexible array. The flexible array should be of a record that contains things such as x and y positions, and x and y velocities or velocity and angle etc.
In your main loop, you have a for loop from 1 .. upper (bullets) to update the position of all the bullets. You'll also have to check for collisions with them, and also you'll probably want to put a range limit on them. Say, if they go 500 pixels, delete them. That would be done by using startX and startY variables. You could then Math.Distance, though that's rather slow. Or you could just run a few if statements.
In any case, check the flexible arrays tutorial, if you don't know how to use them. If you do, check through the code I've included; it's a good example as to how to do this kind of thing.
mike200015
Posted: Sat Apr 30, 2005 10:55 pm Post subject: (No subject)
ok.. thanx.. i got the flexible array to work, but now i have 2 problems:
1. The bullet draws a line sort of, cuz it stretches is when i hold the space.?
2. I have a problem with the collision, i cant figure out how to do it, im using Math.DistancePointLine but i dunno where to put it cuz i gotta check the array of blocks and the array of bullets at the same time but they have 2 different upper values, so i cant really do it in a for loop??
And 1 more question, how can i get it so i can hold space and it will delay like 1 second and shoot the next bullet so i dont havto keep pressing space?
Heres my new code:
Turing:
type block : record
x :int
y :int
hits :int endrecord type bulletvars : record
x :int
y :int
hits :int
col :int endrecord var xvalue :int:= -15 var yvalue :int:=0 var blocks :array1.. 156of block
var colours :array1.. 10ofint:=init(40, 50, 60, 70, 80, 90, 100, 110, 120, 130) var blockcol :array1.. 156ofint var bullet :flexiblearray0.. 0of bulletvars
var chars :arraycharofboolean var shoot :=true var ballx :=maxxdiv2 var bally :=15 var pos :=maxxdiv2 var xmod :=1 var ymod :=1 var tries :=3 var score :=0 var font3 :=Font.New("Courier New:10:bold")%All other font var keyPressed :string(1) var bulbutton :=chr(ORD_SPACE) var bulletx :int:=0 var bullety :int:=8 var yes :=false
new bullet, upper(bullet) + 1
yes :=true %fork bulletfire %fork bulletdelay endif if chars ('x')then exit elsif chars ('p')then%Pauses game setscreen("nooffscreenonly") Font.Draw("GAME PAUSED",maxxdiv2 - 20, maxy - 12, font3, blue) Font.Draw("*Press ENTER To Resume*",maxxdiv2 - Font.Width("*Press ENTER To Resume*", font3) div2, 100, font3, blue) loop getch(keyPressed) exitwhen keyPressed = KEY_ENTER
endloop setscreen("offscreenonly") endif for i :upper(bullet).. upper(bullet)
bullet (i).col :=43
bullet (i).x := pos
bullet (i).y :=8
bullet (i).hits :=0 endfor for i :lower(bullet).. upper(bullet) if yes =truethen Draw.FillOval(bullet (i).x, bullet (i).y, 3, 3, bullet (i).col) if bullet (i).hits ~=1then
bullet (i).y +=1 endif /*
if Math.DistancePointLine (bullet (i).x, bullet (i).y, blocks (i).x, blocks (i).y, blocks (i).x + 40, blocks (i).y) <= 4 then
blocks (i).hits := 1
bullet (i).hits := 1
bullet (i).col := 0
%yes := false
end if
*/ endif endfor for i :1.. upper(blocks) ifMath.DistancePointLine(bullet(i).x, bullet(i).y, blocks (i).x, blocks (i).y, blocks (i).x + 40, blocks (i).y) <= 4then
blocks (i).hits :=1
bullet (i).hits :=1
bullet (i).col :=0 %yes := false endif endfor
xvalue := -15
yvalue :=0 View.Update cls endloop if chars ('x')then exit endif endloop
Cervantes
Posted: Sun May 01, 2005 7:53 am Post subject: (No subject)
1. What I think you're asking is the same as your "And 1 more question" question. I think the problem is that you push space and a bunch of bullets fire off at the same time. You want a cooldown for your weapon. Once again, check the code in the flexible array tutorial; it has an example of this as well.
2. You could use two for loops:
code:
for i : 1 .. upper (bullet)
for j : 1 .. upper (block)
collision detection
end for
end for
But let's think about that for a minute. We probably don't care about anything other than the first few bullets, depending on your cooldown time. We could maybe use upper (bullet) - 1 .. upper (bullet). Also, we only need to check collisions with the outside blocks. Using a 2D array for your blocks would make this much easier.
A question: are the blocks going to ever move around in this game? Or do they stay in a fixed position? If the stay fixed, you could only deal with the upper few bullets and only deal with the outside blocks. You also have to consider the question: do your blocks have spaces between them? If so, and if they move, then you'd have to check collisions for ALL the blocks. Follow my logic?
mike200015
Posted: Sun May 01, 2005 11:36 am Post subject: (No subject)
yea.. im thinking that i can use an if statement around the second for loop, and only check the blocks, if the bullet in the for loop is actually moving, i have a hits record for each bullet and set it to 1 when a bullet hits a block, so i could make an if about if the bullet is onscreen and has not hit a block, then go to the seconf for loop
mike200015
Posted: Sun May 01, 2005 11:42 am Post subject: (No subject)
ok.. so this is what i did for the detection, the only thing, it makes the game run very very slow, and one more thing, the bullet doesnt stop after hitting 1 bullet??
And, How would i make it go faster??
Side Note: Cervantes, i read your tutorial, and it says you cant use flexible arrays with types, but in my game i did, is that bad?
EDIT -- In your tutorial, Cervantes, you have that timeDelay function , do you mind if i use that in my game with my bullets?, i tried it out in my game and it worked to only shoot one bullet at a time, and it gets rid of the problem of hitting more than 1 block.
Code:
Turing:
type block : record
x :int
y :int
hits :int endrecord type bulletvars : record
x :int
y :int
hits :int
col :int endrecord var xvalue :int:= -15 var yvalue :int:=0 var blocks :array1.. 156of block
var colours :array1.. 10ofint:=init(40, 50, 60, 70, 80, 90, 100, 110, 120, 130) var blockcol :array1.. 156ofint var bullet :flexiblearray0.. 0of bulletvars
var chars :arraycharofboolean var shoot :=true var ballx :=maxxdiv2 var bally :=15 var pos :=maxxdiv2 var xmod :=1 var ymod :=1 var tries :=3 var score :=0 var font3 :=Font.New("Courier New:10:bold")%All other font var keyPressed :string(1) var bulbutton :=chr(ORD_SPACE) var bulletx :int:=0 var bullety :int:=8 var yes :=false
new bullet, upper(bullet) + 1
yes :=true %fork bulletfire %fork bulletdelay endif if chars ('x')then exit elsif chars ('p')then%Pauses game setscreen("nooffscreenonly") Font.Draw("GAME PAUSED",maxxdiv2 - 20, maxy - 12, font3, blue) Font.Draw("*Press ENTER To Resume*",maxxdiv2 - Font.Width("*Press ENTER To Resume*", font3) div2, 100, font3, blue) loop getch(keyPressed) exitwhen keyPressed = KEY_ENTER
endloop setscreen("offscreenonly") endif for i :upper(bullet).. upper(bullet)
bullet (i).col :=43
bullet (i).x := pos
bullet (i).y :=8
bullet (i).hits :=0 endfor for i :lower(bullet).. upper(bullet) if yes =truethen if bullet (i).y <= maxy - 30then Draw.FillOval(bullet (i).x, bullet (i).y, 3, 3, bullet (i).col) %Draw.FillOval (bullet (i).x + 10, bullet (i).y, 3, 3, bullet (i).col) if bullet (i).hits ~=1then
bullet (i).y +=1 endif endif endif endfor %bullet and block collision for x :1.. upper(bullet) if bullet (x).y >= 10and bullet (x).y <= maxy - 30and bullet (x).hits ~=1then for i :1.. upper(blocks) if blocks (i).hits ~=1then ifMath.DistancePointLine(bullet (x).x, bullet (x).y, blocks (i).x, blocks (i).y, blocks (i).x + 40, blocks (i).y) <= 4then
blocks (i).hits :=1
bullet (x).hits :=1
bullet (x).col :=0 %yes := false endif endif endfor endif endfor
xvalue := -15
yvalue :=0 %delay (4) View.Update cls endloop if chars ('x')then exit endif endloop
Cervantes
Posted: Sun May 01, 2005 3:58 pm Post subject: (No subject)
Yep, that does go very, very slowly. What kind of graphic are you going to use for the bullet in the final product? Ovals, lines? box? If you use lines or a box, you could ditch the whole Math.DistancePointLine, because you'd only care about what's above the bullet, not anything to the side or below. Also, don't compare with all the blocks, only the outside ones. Try to switch your blocks to use a 2D array.
About flexible arrays and types: what I meant is you can't do this:
code:
type foo : flexible array lower .. upper of
record
bar : string
end record
About the timeDelay function: absolutely!
I hope you have no intention of using that process.
mike200015
Posted: Sun May 01, 2005 5:05 pm Post subject: (No subject)
I'm planning on using a cirlce, like what i have now, thats y im using the Math.DistancePointLine, if i switch to a line or square, would it help speed up the game??
And 2ndly, how can i only check the outside blocks? , do you mean like, the blocks on the outer sides, and at the bottom of each row?
And last, what would making the blocks a 2D array do?
Heres my updated code:
EDIT -- I switched my circle to a Draw.ThickLine and it looks pretty good, and helps it from lagging 2 much. What do you guys think?.. looks ok?
Also, how do i get the line not to show up all the time, i only want it to show when u press space, right now you can see the bullet constantly, ontop of the paddle.?
Turing:
type block : record
x :int
y :int
hits :int endrecord type bulletvars : record
x :int
y :int
hits :int
col :int endrecord var xvalue :int:= -15 var yvalue :int:=0 var blocks :array1.. 156of block
var colours :array1.. 10ofint:=init(40, 50, 60, 70, 80, 90, 100, 110, 120, 130) var blockcol :array1.. 156ofint var bullet :flexiblearray1.. 1of bulletvars
var chars :arraycharofboolean %var shoot := true var ballx :=maxxdiv2 var bally :=15 var pos :=maxxdiv2 var xmod :=1 var ymod :=1 var tries :=3 var score :=0 var font3 :=Font.New("Courier New:10:bold")%All other font var keyPressed :string(1) var bulbutton :=chr(ORD_SPACE) var bulletx :int:=0 var bullety :int:=8 var timeLast :=0 %var shoot :=false
Posted: Sun May 01, 2005 7:48 pm Post subject: (No subject)
Yes, looks like switching away from ovals sped the game up.
Check only the outside blocks by making the blocks into a 2D array. That way, you only need to check the upper element of each column. Provided your blocks will always remain stationary, you won't even need to check the side blocks.
As for seeing the bullet constantly, I'm not sure (haven't looked at code), but I'll run over the basis: your flexible array is from 1 to 0 when there's no bullets on the screen. Whenever the fire key is pressed (and also when cooldown is true) create a new element of the flexible array. Drawing should be as simple as a for loop from 1 to upper (bullet) and a draw command (think line, in this case).
mike200015
Posted: Sun May 01, 2005 8:14 pm Post subject: (No subject)
at the begining, my flexible array is 1..1 cuz if i do 1..0 then it gives me an error of array subscript out of range, run my game if u can, and change the 1..1 to 1..0 and ull c wat i mean.
And as for the 2d array, i should scrap wat i have now about how my blocks are drawn, and change it?
mike200015
Posted: Mon May 02, 2005 5:35 pm Post subject: (No subject)
ok.. i got my flexible array thing fixed, and now it doesnt show all the time.
The next thing i was trying to do, is what you have, Cervantes, in your little program you made for flexible arrays, to delete the upper array after the bullet hits a block. It works, but only if 1 bullet is shot, if you shoot 2 bullets, once the 1st bullet hits a block, i get an error that array subscript is out of range.
Could you check it out, and see what i did wrong?
Heres the new code: ( I also added missiles to the game, and that is Shift to shoot them)
Turing:
type block : record
x :int
y :int
hits :int endrecord type bulletvars : record
x :int
y :int
hits :int
col :int endrecord type missilevars : record
x :int
y :int
hits :int
col :int endrecord var xvalue :int:= -15 var yvalue :int:=0 var blocks :array1.. 156of block
var colours :array1.. 10ofint:=init(40, 50, 60, 70, 80, 90, 100, 110, 120, 130) var blockcol :array1.. 156ofint var bullet :flexiblearray1.. 0of bulletvars
var missile :flexiblearray1.. 0of missilevars
var chars :arraycharofboolean var ballx :=maxxdiv2 var bally :=15 var pos :=maxxdiv2 var xmod :=1 var ymod :=1 var tries :=3 var score :=0 var bammo :=25 var mammo :=10 var font3 :=Font.New("Courier New:10:bold")%All other font var keyPressed :string(1) var bulbutton :=chr(ORD_SPACE) var timeLast :=0
function cooldown (timeDelay :int):boolean ifTime.Elapsed - timeLast >= timeDelay then resulttrue endif resultfalse end cooldown
for i :1.. upper(blocks)
blocks (i).hits :=0 endfor
loop cls for i :1.. 156 randint(blockcol (i),1, 10) endfor setscreen("offscreenonly") loop for i :1.. 156 if(i - 1)rem12=0then
xvalue +=45
yvalue :=190 endif
blocks (i).x := xvalue
blocks (i).y := yvalue
if blocks (i).hits ~=1then Draw.FillBox(blocks (i).x, blocks (i).y + 2, blocks (i).x + 40, blocks (i).y + 10, colours (blockcol (i))) endif
yvalue +=12 endfor Draw.FillBox(pos - 25, 0, pos + 25, 5, 1)%user paddle Font.Draw("Tries Remaining: " + intstr(tries),2, maxy - 12, font3, blue) Font.Draw("Score: " + intstr(score),maxx - 83, maxy - 12, font3, blue) Font.Draw("Bullets: " + intstr(bammo),maxx - (135 + Font.Width("Bullets: ", font3)),maxy - 12, font3, blue) Font.Draw("Missiles: " + intstr(mammo),maxx - (252 + Font.Width("Missiles: ", font3)),maxy - 12, font3, blue) Draw.Line(0, maxy - 20, maxx, maxy - 20, RGB.AddColor(0.1, 0.1, 0.1))%top boundary line Input.KeyDown(chars) if chars (KEY_LEFT_ARROW)and pos - 25 > 0then%Moves paddle left
pos -=2 elsif chars (KEY_RIGHT_ARROW)and pos + 25 < maxxthen%Moves paddle right
pos +=2 endif if bammo > 0then if chars (bulbutton)then if cooldown (300)then new bullet, upper(bullet) + 1
bullet (upper(bullet)).col :=43
bullet (upper(bullet)).x := pos
bullet (upper(bullet)).y :=8
bullet (upper(bullet)).hits :=0
timeLast :=Time.Elapsed
bammo -=1 endif endif endif if mammo > 0then if chars (KEY_SHIFT)then if cooldown (300)then new missile, upper(missile) + 1
missile (upper(missile)).col :=43
missile (upper(missile)).x := pos
missile (upper(missile)).y :=8
missile (upper(missile)).hits :=0
timeLast :=Time.Elapsed
mammo -=1 endif endif endif if chars ('x')then exit elsif chars ('p')then%Pauses game setscreen("nooffscreenonly") Font.Draw("GAME PAUSED",maxxdiv2 - 44, 140, font3, blue) Font.Draw("*Press ENTER To Resume*",maxxdiv2 - Font.Width("*Press ENTER To Resume*", font3) div2, 100, font3, blue) loop getch(keyPressed) exitwhen keyPressed = KEY_ENTER
endloop setscreen("offscreenonly") endif for i :1.. upper(bullet) if bullet (i).y <= maxy - 60then Draw.ThickLine(bullet (i).x, bullet (i).y, bullet (i).x, bullet (i).y + 6, 2, bullet (i).col) if bullet (i).hits ~=1then
bullet (i).y +=1 endif endif endfor for i :1.. upper(missile) if missile (i).y <= maxy - 60then Draw.ThickLine(missile (i).x, missile (i).y, missile (i).x, missile (i).y + 5, 5, missile (i).col) if missile (i).hits ~=2then
missile (i).y +=1 endif endif endfor %bullet and block collision for x :1.. upper(bullet) if bullet (x).y >= 10and bullet (x).y <= maxy - 30and bullet (x).hits ~=1then for i :1.. upper(blocks) if blocks (i).hits ~=1then if bullet (x).x >= blocks (i).x and bullet (x).x <= blocks (i).x + 40and bullet (x).y + 8 >= blocks (i).y then
blocks (i).hits :=1
bullet (x).hits :=1
bullet (x).col :=0
score +=1 %exit for k : x + 1.. upper(bullet)
bullet (k - 1):= bullet (k) endfor new bullet, upper(bullet) - 1 exit endif endif endfor endif endfor for x :1.. upper(missile) if missile (x).y >= 10and missile (x).y <= maxy - 30and missile (x).hits ~=2then for i :1.. upper(blocks) if blocks (i).hits ~=1then if missile (x).x + 5 >= blocks (i).x and missile (x).x - 5 <= blocks (i).x + 40and missile (x).y + 8 >= blocks (i).y then
blocks (i).hits :=1
missile (x).hits +=1
missile (x).col :=0
score +=1 for k : x + 1.. upper(missile)
missile (k - 1):= missile (k) endfor new missile, upper(missile) - 1 exit endif endif endfor endif endfor
xvalue := -15
yvalue :=0 %delay (4) View.Update cls endloop if chars ('x')then exit endif endloop
Cervantes
Posted: Mon May 02, 2005 6:09 pm Post subject: (No subject)
The reason for this is as follows:
We are going to examine this section of code:
code:
%bullet and block collision
for x : 1 .. upper (bullet)
if bullet (x).y >= 10 and bullet (x).y <= maxy - 30 and bullet (x).hits ~= 1 then
for i : 1 .. upper (blocks)
if blocks (i).hits ~= 1 then
if bullet (x).x >= blocks (i).x and bullet (x).x <= blocks (i).x + 40 and bullet (x).y + 8 >= blocks (i).y then
blocks (i).hits := 1
bullet (x).hits := 1
bullet (x).col := 0
score += 1
%exit
for k : x + 1 .. upper (bullet)
bullet (k - 1) := bullet (k)
end for
new bullet, upper (bullet) - 1
exit
end if
end if
end for
end if
end for
Let's assume all those if statements are true. We go all the way into it, and we delete that particular bullet. Then we exit the for loop that checks the blocks, and restart at the top of the bullet's for loop. But now we've got one less bullet, and yet x has still increased. Thus, x is now > upper (bullet), because we decreased upper (bullet).
To fix this, check out the tut about Removing an Element from a Flexible Array within a For Loop. It's not a great tutorial, mind you, because it was really a question I posted in Help that got kinda got transformed into a tutorial. I don't even know the best solution to the problem: as you'll soon find out, I took Bacchus idea, and fixed it so it would work in a few more situations than his original idea did. But by doing this I also used lots of cpu processing, which is really bad in your case.
In any case, read the tutorial, and maybe you can spend some time on the problem and post the best solution.
mike200015
Posted: Mon May 02, 2005 9:06 pm Post subject: (No subject)
k.. ill check out the tutorial, thanx!
And also, about the 2D array for the blocks that you said to do, how should i change my blocks now to make it like you suggested?
mike200015
Posted: Mon May 02, 2005 9:37 pm Post subject: (No subject)
it prevents the error of array subscript out of range coming up, but then the last bullet of the array doesnt stop, it destroys all the blocks in its row.
mike200015
Posted: Mon May 02, 2005 9:54 pm Post subject: (No subject)
nevermind, i got it to work, i jus added the suggestion that Bacchus gave in your question, i added in:
Turing:
exitwhen x+1>upper (bullet)
and it works fine, i was trying other things cuz i didnt think that would work, and then i tried it, and it worked! Thanx so much Cervantes, and Bacchus with your idea! lol
The only thing still, is that i thought by doing the whole thing with deleting the upper, it would prevent my game from slowing down, but it doesnt really, i dont think. After i shoot alot of bullets, then it slows down my game permanently. How would i prevent this from happening?