Posts: 86
Threads: 22
Joined: Sep 2019
Reputation:
0
I would like to go a step further and learn how to create a more advanced shot. I am going to show a video where the player's ship is seen shooting a beam that grows and only decreases when colliding with enemies.
To see it more clearly, you have to put the video at minute 2:04, where it faces a large ship and it can be seen how the player's ship launches a blue shot that is a kind of lightning that grows until it hits the big ship, and when it hits it doesn't keep growing.
The question would be how you can program this type of shot.
Posts: 173
Threads: 19
Joined: Jan 2018
Reputation:
3
Hi,
Not easy to show a simple example for this initially - I will give it some more thought, but this is my attempt at the moment, with just one "enemy"......I think if you want more enemies on screen, then the approach will need to introduce more tables to the code.
Code: visible screen_w = 640,screen_h = 480
'Open a window
set window "Moving explosion",screen_w,screen_h
'enable double buffering
set redraw off
visible enemy_x = 150;enemy_x_inc = 1
visible enemy_y = 100
visible enemy_poly = [enemy_x, enemy_y, enemy_x + 100, enemy_y + 100, enemy_x + 150, enemy_y + 50,enemy_x + 200, enemy_y + 100,
enemy_x + 300, enemy_y]
visible ship_x = 270
visible ship_y = 430
visible explosion_y,explosion_colour = [0,0,0]
visible explosion_beam_colour = [255,255,255]
##############################################################################################
####################################### GAME LOOP #########################################
##############################################################################################
do
colour_timer = (colour_timer + 1) % 6
'change the bullet colours randomly
if colour_timer > 4
'explosion_colour = [rnd(127) + 128,rnd(127) + 128,rnd(127)+ 128]
explosion_colour = [rnd(127) + 128,128,128]
explosion_beam_colour = [rnd(127) ,rnd(127) ,rnd(127)]
endif
'clear the screen
set color 255,255,255
cls
set color 0,0,0
'move enemy
enemy_poly = [enemy_x, enemy_y, enemy_x + 100, enemy_y + 100, enemy_x + 150, enemy_y + 50,enemy_x + 200, enemy_y + 100,
enemy_x + 300, enemy_y]
enemy_x = enemy_x + enemy_x_inc
if enemy_x > screen_w - 300 or enemy_x < 0
enemy_x_inc = - enemy_x_inc
endif
'move ship
if keydown(KEY_LEFT) then ship_x = ship_x - 1
if keydown(KEY_RIGHT) then ship_x = ship_x + 1
if keydown(KEY_UP) then ship_y = ship_y - 1
if keydown(KEY_DOWN) then ship_y = ship_y + 1
' draw enemy ship
set color 0,255,0
draw poly enemy_poly, true
'fire bullet
if keydown(KEY_SPACE )
set color explosion_beam_colour[0],explosion_beam_colour[1],explosion_beam_colour[2 ]
if ship_x + 32 > enemy_x and ship_x < enemy_x + 300
draw rect ship_x + 16,explosion_y,32,ship_y - explosion_y,true ' short beam
else
draw rect ship_x + 16,0,32,ship_y ,true'long beam
endif
endif
'draw explosion
if keydown(KEY_SPACE )
find_explosion_y()
set color explosion_colour[0],explosion_colour[1],explosion_colour[2 ]
draw ellipse ship_x + 32,explosion_y,16,8,1
endif
set color 64,64,64
'draw ship
draw rect ship_x,ship_y,64,16,1
set caret 160,20
write "MOVE WITH ARROW KEYS, FIRE WITH SPACE BAR"
'copy back buffer to the screen
redraw
'cap FPS to 60
fwait 60
until keydown(KEY_ESCAPE)
#########################################################################################
################################# FUNCTIONS ###########################################
#########################################################################################
function find_explosion_y()
if ship_x + 16 >= enemy_poly[0] and ship_x + 16 < enemy_poly[2]
explosion_y = (enemy_poly[3] - enemy_poly[1]) / (enemy_poly[2] - enemy_poly[0]) * (ship_x - enemy_poly[0]) + enemy_poly[1] + 16
elseif ship_x + 16 >= enemy_poly[2] and ship_x + 16 < enemy_poly[4]
explosion_y = (enemy_poly[5] - enemy_poly[3]) / (enemy_poly[4] - enemy_poly[2]) * (ship_x - enemy_poly[2]) + enemy_poly[3] - 48
elseif ship_x + 16 >= enemy_poly[4] and ship_x + 16 < enemy_poly[6]
explosion_y = (enemy_poly[7] - enemy_poly[5]) / (enemy_poly[6] - enemy_poly[4]) * (ship_x - enemy_poly[4]) + enemy_poly[5] + 16
elseif ship_x + 16 >= enemy_poly[6] and ship_x + 16 < enemy_poly[8]
explosion_y = (enemy_poly[9] - enemy_poly[7]) / (enemy_poly[8] - enemy_poly[6]) * (ship_x - enemy_poly[6]) + enemy_poly[7] - 48
else
explosion_y = 0
endif
endfunc
Posts: 86
Threads: 22
Joined: Sep 2019
Reputation:
0
Thank you very much Kevin.
The example is very good and it works very well, it is true that it is not easy but I think that with time and practice it can be understood, if you have more examples like this, do not hesitate to show them to me.
Examples like this are very helpful to continue learning and improving. Regards
Posts: 86
Threads: 22
Joined: Sep 2019
Reputation:
0
Last question about the shots.
At minute 2:04 a large ship appears and starts shooting many bullets in different directions and every so often the pattern of those shots changes.
How can you program these types of shots?
Posts: 173
Threads: 19
Joined: Jan 2018
Reputation:
3
(03-20-2023, 01:24 PM)aliensoldier Wrote: Last question about the shots.
At minute 2:04 a large ship appears and starts shooting many bullets in different directions and every so often the pattern of those shots changes.
How can you program these types of shots?
If I were to do this, I would use this basic method, then expand it using a timer to introduce different patterns of bullets - this code just has the one pattern currently.
Code: visible screen_w = 640,screen_h = 480
'Open a window
set window "Bullets",screen_w,screen_h
'enable double buffering
set redraw off
enemy = [x:screen_w/2,y:100,r:64]
bullets = []
angle = - 0.5
for i = 0 to 5
bullets[sizeof(bullets)] = [x:screen_w/2,y:100,x_inc:sin(angle),y_inc : cos(angle)]
angle = angle + 0.2
next
##############################################################################################
####################################### GAME LOOP #########################################
##############################################################################################
do
'clear the screen
set color 255,255,255
cls
set color 0,0,0
draw ellipse enemy.x,enemy.y,enemy.r,enemy.r
foreach bullet in bullets
draw rect bullet.x,bullet.y,4,4
bullet.x = bullet.x + bullet.x_inc
bullet.y = bullet.y + bullet.y_inc
next
'copy back buffer to the screen
redraw
'cap FPS to 60
fwait 60
until keydown(KEY_ESCAPE)
Unfortunately I do not have much time available today, but I will expand the code in the next day or two if required (but happy for anyone else to jump in with thier own ideas).
Aliensoldier - are you just looking for the changing bullet patterns, or do you need to see the bullets being removed from the table when they leave the screen, or any collision detection for the bullets?
Posts: 86
Threads: 22
Joined: Sep 2019
Reputation:
0
(03-20-2023, 04:36 PM)kcfb Wrote: (03-20-2023, 01:24 PM)aliensoldier Wrote: Last question about the shots.
At minute 2:04 a large ship appears and starts shooting many bullets in different directions and every so often the pattern of those shots changes.
How can you program these types of shots?
If I were to do this, I would use this basic method, then expand it using a timer to introduce different patterns of bullets - this code just has the one pattern currently.
Code: visible screen_w = 640,screen_h = 480
'Open a window
set window "Bullets",screen_w,screen_h
'enable double buffering
set redraw off
enemy = [x:screen_w/2,y:100,r:64]
bullets = []
angle = - 0.5
for i = 0 to 5
bullets[sizeof(bullets)] = [x:screen_w/2,y:100,x_inc:sin(angle),y_inc : cos(angle)]
angle = angle + 0.2
next
##############################################################################################
####################################### GAME LOOP #########################################
##############################################################################################
do
'clear the screen
set color 255,255,255
cls
set color 0,0,0
draw ellipse enemy.x,enemy.y,enemy.r,enemy.r
foreach bullet in bullets
draw rect bullet.x,bullet.y,4,4
bullet.x = bullet.x + bullet.x_inc
bullet.y = bullet.y + bullet.y_inc
next
'copy back buffer to the screen
redraw
'cap FPS to 60
fwait 60
until keydown(KEY_ESCAPE)
Unfortunately I do not have much time available today, but I will expand the code in the next day or two if required (but happy for anyone else to jump in with thier own ideas).
Aliensoldier - are you just looking for the changing bullet patterns, or do you need to see the bullets being removed from the table when they leave the screen, or any collision detection for the bullets?
Only the patterns, although I would like to see how the different patterns are programmed.
I liked the example that you have shown, when you have time and if you feel like it show me how to make the other patterns. Thank you
Posts: 173
Threads: 19
Joined: Jan 2018
Reputation:
3
Here's some more patterns - not exact duplicates of the ones on YouTube, but you should be able to change them to your taste:
Code: visible screen_w = 640,screen_h = 480
'Open a window
set window "Bullets",screen_w,screen_h
'enable double buffering
set redraw off
visible enemy = [x:screen_w/2,y:100,x_inc : 1,r:64]
visible bullets = [],choice = 0
add_bullets() ' set up the first lot of bullets
##############################################################################################
####################################### GAME LOOP #########################################
##############################################################################################
do
'This releases new bullets every 250 milliseconds - this value can
'be changed to alter the rate of release.
bullet_change = bullet_change + 1
if bullet_change > 250
bullet_change = 0
add_bullets()
endif
'==================================
'clear the screen
set color 255,255,255
cls
set color 0,0,0
'Move the enemy from side to side
enemy.x = enemy.x + enemy.x_inc
if enemy.x - enemy.r < 100 or enemy.x + enemy.r > screen_w - 100
enemy.x_inc = - enemy.x_inc
endif
'Draw the enemy
draw ellipse enemy.x,enemy.y,enemy.r,enemy.r
'Draw the bullets
foreach bullet in bullets
if bullet.timer > 0 then bullet.timer = bullet.timer - 1
if bullet.timer = 1
bullet.x = enemy.x
bullet.y = enemy.y
endif
if bullet.timer = 0
draw rect bullet.x,bullet.y,4,4
bullet.x = bullet.x + bullet.x_inc
bullet.y = bullet.y + bullet.y_inc
endif
next
'=============================================
set caret screen_w / 2,10
center "WAVE NUMBER " + choice
'copy back buffer to the screen
redraw
'cap FPS to 60
fwait 60
until keydown(KEY_ESCAPE)
#########################################################################################
################################# FUNCTIONS ###########################################
#########################################################################################
function add_bullets()
choice = rnd(10) + 1 ' Pick a random bullet wave each time
if choice = 1
angle = - 0.5
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle),y_inc : cos(angle),timer:0]
angle = angle + 0.2
next
else if choice = 2
angle = - 0.5
for i = 5 to 0 step - 1
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 2,y_inc : cos(angle ) * 2,timer : i * 30]
angle = angle + 0.2
next
else if choice = 3
angle = - 0.5
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 2,y_inc : cos(angle ) * 2,timer : i * 30]
angle = angle + 0.2
next
else if choice = 4
angle = - 0.5
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 3,y_inc : cos(angle ) * 3,timer : i * 30]
angle = angle + 0.1
next
else if choice = 5
angle = - 0.5
for i = 11 to 0 step - 1
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 3,y_inc : cos(angle ) * 3,timer : i * 30]
angle = angle + 0.1
next
else if choice = 6
angle = - 0.5
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle),y_inc : cos(angle),timer:0]
angle = angle + 0.1
next
else if choice = 7
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin((rnd(20)-10) / 20),y_inc : cos((rnd(20)-10) / 20),timer:i * (rnd(20) + 5)]
next
else if choice = 8
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin((rnd(10)) / 10) ,y_inc : cos((rnd(10)) / 10) ,timer:i * 20]
next
else if choice = 9
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin((rnd(-10)) / 10) ,y_inc : cos((rnd(-10)) / 10) ,timer:i * 20]
next
else if choice = 10
angle = - 0.5
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle),y_inc : cos(angle),timer:0]
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 1.5,y_inc : cos(angle) * 1.5,timer:0]
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 2 ,y_inc : cos(angle) * 2,timer:0]
angle = angle + 0.1
next
endif
endfunc
You will need to add some code to remove the bullets from the table once they have left the screen.
Hope this helps - Kevin.
Posts: 86
Threads: 22
Joined: Sep 2019
Reputation:
0
Thank you very much Kevin.
I have changed my mind and I think it would be good if you show how to eliminate the shots when leaving the screen, to see how you do it and learn.
Posts: 173
Threads: 19
Joined: Jan 2018
Reputation:
3
To remove the bullets, I would just add this code at the start of the game loop, pinched from Marcus from an earlier answer:
Code: removeList = []
foreach b in bullets
if b.y > screen_h
removeList[sizeof(removeList)] = b
endif
next
foreach b in removeList free val bullets, b
It just tests for bullets disappearing below the bottom of the screen. You could add to it to test for bullets disappearing to the left and right of the screen if you want, but probably not required in this instance.
Here is the full code, which includes a display to show the changing size of the bullets table:
Code: visible screen_w = 640,screen_h = 480
'Open a window
set window "Bullets",screen_w,screen_h
'enable double buffering
set redraw off
visible enemy = [x:screen_w/2,y:100,x_inc : 1,r:64]
visible bullets = [],choice = 0
add_bullets() ' set up the first lot of bullets
##############################################################################################
####################################### GAME LOOP #########################################
##############################################################################################
do
'This releases new bullets every 250 milliseconds - this value can
'be changed to alter the rate of release.
bullet_change = bullet_change + 1
if bullet_change > 250
bullet_change = 0
add_bullets()
endif
removeList = [] ' used to remove bullets from the bullets table when they go below the screen
foreach b in bullets
if b.y > screen_h
removeList[sizeof(removeList)] = b
endif
next
foreach b in removeList free val bullets, b
'==================================
'clear the screen
set color 255,255,255
cls
set color 0,0,0
'Move the enemy from side to side
enemy.x = enemy.x + enemy.x_inc
if enemy.x - enemy.r < 100 or enemy.x + enemy.r > screen_w - 100
enemy.x_inc = - enemy.x_inc
endif
'Draw the enemy
draw ellipse enemy.x,enemy.y,enemy.r,enemy.r
'Draw the bullets
foreach bullet in bullets
if bullet.timer > 0 then bullet.timer = bullet.timer - 1
if bullet.timer = 1
bullet.x = enemy.x
bullet.y = enemy.y
endif
if bullet.timer = 0
draw rect bullet.x,bullet.y,4,4
bullet.x = bullet.x + bullet.x_inc
bullet.y = bullet.y + bullet.y_inc
endif
next
'=============================================
set caret screen_w / 2,10
center "WAVE NUMBER " + choice
center "sizeof(bullets) = " + sizeof(bullets)
'copy back buffer to the screen
redraw
'cap FPS to 60
fwait 60
until keydown(KEY_ESCAPE)
#########################################################################################
################################# FUNCTIONS ###########################################
#########################################################################################
function add_bullets()
choice = rnd(10) + 1 ' Pick a random bullet wave each time
if choice = 1
angle = - 0.5
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle),y_inc : cos(angle),timer:0]
angle = angle + 0.2
next
else if choice = 2
angle = - 0.5
for i = 5 to 0 step - 1
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 2,y_inc : cos(angle ) * 2,timer : i * 30]
angle = angle + 0.2
next
else if choice = 3
angle = - 0.5
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 2,y_inc : cos(angle ) * 2,timer : i * 30]
angle = angle + 0.2
next
else if choice = 4
angle = - 0.5
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 3,y_inc : cos(angle ) * 3,timer : i * 30]
angle = angle + 0.1
next
else if choice = 5
angle = - 0.5
for i = 11 to 0 step - 1
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 3,y_inc : cos(angle ) * 3,timer : i * 30]
angle = angle + 0.1
next
else if choice = 6
angle = - 0.5
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle),y_inc : cos(angle),timer:0]
angle = angle + 0.1
next
else if choice = 7
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin((rnd(20)-10) / 20),y_inc : cos((rnd(20)-10) / 20),timer:i * (rnd(20) + 5)]
next
else if choice = 8
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin((rnd(10)) / 10) ,y_inc : cos((rnd(10)) / 10) ,timer:i * 20]
next
else if choice = 9
for i = 0 to 5
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin((rnd(-10)) / 10) ,y_inc : cos((rnd(-10)) / 10) ,timer:i * 20]
next
else if choice = 10
angle = - 0.5
for i = 0 to 11
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle),y_inc : cos(angle),timer:0]
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 1.5,y_inc : cos(angle) * 1.5,timer:0]
bullets[sizeof(bullets)] = [x:enemy.x,y:enemy.y,x_inc:sin(angle) * 2 ,y_inc : cos(angle) * 2,timer:0]
angle = angle + 0.1
next
endif
endfunc
Posts: 86
Threads: 22
Joined: Sep 2019
Reputation:
0
Thanks a lot for the help, Kevin.
|