Last active
May 1, 2023 11:11
-
-
Save horstjens/e09e486bd244f21dd07576c2b55ab5cd to your computer and use it in GitHub Desktop.
doppeldecker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# requriements: | |
# sudo pip3 install vpython | |
# sudo pip3 install pygame | |
import vpython as v | |
import random | |
import pygame | |
#except ModuleNotFoundError: | |
# print("I could not import pygame - joystick support is disabled. Try to (re)install pygame") | |
#delete, backspace, page up, page down, home, end, left, up, right, down, numlock, scrlock, f1, f2, f3, f4, f5, f6, f7, f8. Windows and Linux also have f9, f11, f12, insert | |
#if you hold down the shift key and press F3, key will be the character string 'shift+f3', which you can test for explicitly. If you hold down all three modifier keys, you get 'ctrl+alt+shift+f3'; the order is always ctrl, alt, shift. | |
# constants | |
class Game: | |
scene1 = v.canvas(title="Doppeldecker", | |
width=800, | |
height=600, | |
center=v.vector(0, 0, 0), | |
background=v.vector(0.8, 0.8, 1), | |
resizable=False | |
) | |
#camera_mode = "follow" | |
scene1.autoscale = False | |
scene1.userspin = False | |
camera_delay = 0.0 # seconds | |
camera_history = [] | |
# scene1.range = 200 | |
max_depth = -10 # lowest point of the landscape? | |
dt = 0.005 # delta t | |
world = 100 # half lenght (x,y) of world | |
rotation = 60 # rotation speed of plane | |
cooldown_gun = 0.05 | |
cooldown_flak = 0.20 | |
cooldown_bomb = 0.3 | |
cooldown_rocket = 0.12 | |
drag_player = 5.5 # 5.515 | |
drag_bullet = 0.1 | |
drag_bomb = 2.0 | |
radius_player = 0.15 # for ground collision hitbox | |
cannon_power = 17000 # bullet speed at start | |
rocket_power = 0.25 | |
rocket_fuel = 0.5 # sec | |
lift_factor = 0.5 | |
mass_player = 0.1 | |
mass_bullet = 0.011 | |
mass_bomb = 0.05 | |
mass_rocket = 0.03 | |
mass_particle = 0.005 | |
flak_range = 40 # range when flak start shooting at player | |
flak_crit_distance = 0.5 # how close flak shell must be to player center to make damage | |
g = 9.81 | |
#g_player = 9.81 | |
#g_bullet = 9.81 | |
#g_bomb = 5.2 | |
particle_list = [] | |
tank_list = [] | |
bullet_list = [] | |
explosion_list = [] | |
static_list = [] | |
bomb_list = [] | |
rocket_list = [] | |
target_list = [] | |
ring_list = [] | |
#flak_list = [] | |
flak_barrel_list = [] | |
ring_center_distance = 1 # 1 is hard, 10 is super easy | |
# UI widgets, initialized in function main() | |
vlist = [] # list for ground vertices | |
label_dt = None | |
label_lift = None | |
label_ring_center_distance = None | |
label_rotation = None | |
label_delay = None | |
ring_index = 0 | |
my_ring = None | |
max_power = 20 # values over 20 make the plane slower.... bug in physic ? | |
min_power = 0 | |
def create_sun(): | |
s = v.simple_sphere( | |
pos = v.vector(random.uniform(-Game.world,Game.world), # x | |
random.uniform(50,60), # y | |
random.uniform(-Game.world,Game.world) # z | |
), | |
#radius = random.random()*2 + 0.5 # 0.5 - 2.5 | |
radius = random.uniform(0.5, 2.5), # 0.5 bis 2.5 | |
color = v.vector(1,1,0), #100%red, 100%green, 0%blue = gelb | |
shininess = 0.6, # häääääää ? | |
emissive = True, # leuchtet? | |
) | |
return s | |
def create_ring(): | |
r = v.ring(pos=v.vector(random.randint(-Game.world,Game.world), random.randint(5,15), random.randint(-Game.world,Game.world)), | |
axis=v.vector(random.random()*2-1,0,random.random()*2-1), | |
radius= 2.5 + random.random()*7, | |
thickness=0.1 + random.random()*2, | |
) | |
return r | |
def create_flak(): | |
h = random.randint(5,12) # height | |
body = v.box( | |
size=v.vector(0.5,h,0.5), | |
pos= v.vector(2,h/2,2), | |
axis = v.vector(1,0,0), | |
color = v.vector(1,1,0), | |
) | |
ball = v.simple_sphere( | |
size = v.vector(2,2,2), | |
pos = v.vector(2,h,2), | |
axis = v.vector(1,0,0), | |
color = v.vector(0.8,0.8,0) | |
) | |
flak = v.compound([body, ball]) | |
x = random.uniform(-Game.world +1, Game.world -1) | |
z = random.uniform(-Game.world +1, Game.world -1) | |
y = f(x,z) * Game.max_depth | |
flak.pos = v.vector(x, y + h/2, z) | |
flak.hitpoints = 100 | |
flak.rot_speed_y = 30 | |
flak.rot_speed_x = 20 | |
Game.target_list.append(flak) | |
create_flak_barrel(flak) | |
def create_flak_barrel(flak): | |
barrel = v.cylinder( pos=v.vector(0,0,0), | |
radius = 0.2, | |
axis = v.vector(3,0,0), | |
color = v.vector(0.1,0.1,0.1) | |
) | |
barrel.pos = v.vector(flak.pos.x, flak.pos.y + flak.size.y/2 -0.5, flak.pos.z) | |
barrel.age = 0 | |
barrel.block_gun_until = 0 | |
barrel.move = v.vector(0,0,0) # important for bullets! | |
barrel.flak = flak | |
Game.flak_barrel_list.append(barrel) | |
def create_tank(): | |
body = v.box( | |
size=v.vector(2,0.5,1), | |
pos=v.vector(0, 0.25 ,0), | |
axis=v.vector(1,0,0), | |
color=v.vector(0,0, random.uniform(.65,0.90)), | |
) | |
turret = v.cylinder( | |
size=v.vector(0.3,0.75, 0.75), | |
pos = v.vector(0, 0.5, 0), | |
axis = v.vector(0,1,0), | |
color=v.vector(0.2,0.2,0.2) | |
) | |
cannon = v.cylinder( | |
size=v.vector(2 , 0.1, 0.1), | |
axis= v.vector(1,0,0), | |
pos = v.vector(-0.25, 0.75, 0 ), | |
color = v.vector(0.8,0.8,1.0) | |
) | |
tank = v.compound([body, turret, cannon]) | |
tank.size = v.vector(4,1,2) | |
#tank.pos.y += 2 | |
tank.pos = v.vector(random.randint(-Game.world+1, Game.world-1),0.25, random.randint(-Game.world+1, Game.world-1)) | |
tank.power = random.uniform(1, 3) | |
tank.angle = random.random() * 360 | |
tank.rotate(angle=v.radians(tank.angle), axis=v.vector(0,1,0) ) | |
tank.move = tank.axis.norm() * tank.power | |
tank.hitpoints = 100 | |
#tank.hy = v.vector(0, -10, 0) | |
#v.attach_arrow(tank, "hy" , color=v.vector(1,1,1) ) | |
Game.tank_list.append(tank) | |
Game.target_list.append(tank) | |
def create_cross(): | |
"""create three arrows (pointing to x, y, z) at pos (0,0,0)""" | |
xpointer = v.arrow( | |
pos=v.vector(0, 0, 0), | |
axis=v.vector(1, 0, 0), | |
shaftwidth=0.1, | |
color=v.color.yellow, | |
) | |
ypointer = v.arrow( | |
pos=v.vector(0, 0, 0), | |
axis=v.vector(0, 1, 0), | |
shaftwidth=0.1, | |
color=v.color.purple, | |
) | |
zpointer = v.arrow( | |
pos=v.vector(0, 0, 0), | |
axis=v.vector(0, 0, 1), | |
shaftwidth=0.1, | |
color=v.color.blue, | |
) | |
cross = v.compound((xpointer, ypointer, zpointer)) | |
cross.pos = v.vector(0,1,0) | |
xlabel = v.label( | |
pos=cross.pos + xpointer.axis, | |
text='x', xoffset=0, yoffset=5, space=1, height=16, border=4 | |
) | |
ylabel = v.label( | |
pos=cross.pos + ypointer.axis, | |
text='y', xoffset=0, yoffset=5, space=1, height=16, border=4 | |
) | |
zlabel = v.label( | |
pos=cross.pos + zpointer.axis, | |
text='z', xoffset=0, yoffset=5, space=1, height=16, border=4 | |
) | |
return cross | |
def create_player(): | |
# ----- player (flugzeug) ----- | |
body = v.box( | |
# x y z | |
size=v.vector(2,0.25,0.25), | |
pos = v.vector(0,0,0), | |
color=v.vector(0.72,0.42,0) | |
) | |
upperwing = v.box( | |
# x y z | |
size=v.vector(0.5,0.05,2), | |
pos = v.vector(0.5,0.2,0), | |
color=v.vector(0.26,0.99,0.78), | |
) | |
lowerwing = v.box( | |
# x y z | |
size=v.vector(0.5,0.05,2), | |
pos = v.vector(0.5,-0.2,0), | |
color=v.vector(0.26,0.99,0.78),) | |
#make_trail=True, | |
#trail_type="points", | |
#interval=10, | |
#retain=150, | |
#trail_color=v.vector(0,1,0) | |
#) | |
# höhenruder | |
rudder1 = v.box( | |
size=v.vector(0.2, 0.05, 1), | |
pos=v.vector(-1, 0, 0), | |
color=v.vector(0.26, 0.99, 0.78), | |
) | |
# seitenruder | |
rudder2 = v.box( | |
# x y z | |
size=v.vector(0.2, 0.5, 0.05), | |
pos=v.vector(-1, 0.25, 0), | |
color=v.vector(0.26, 0.99, 0.78), | |
) | |
player = v.compound([body, upperwing, lowerwing, rudder1, rudder2],) | |
#make_trail=True, | |
#trail_type="points", | |
#interval=10, | |
#retain=150, | |
#trail_color=v.vector(0,1,0)) | |
player.axis = v.vector(1, 0, 0) | |
player.pos = v.vector(0, 2, 0) | |
player.pos_old = v.vector(0, 2, 0) | |
player.power = 0.0 | |
player.block_gun_until = 0.0 | |
player.block_bomb_until = 0.0 | |
player.block_rocket_until = 0.0 | |
player.age = 0.0 | |
player.move = v.vector(0,0,0) | |
player.points = 0 #https://vpython.org/ | |
player.hitpoints = 100 | |
player.modus = "ground" | |
player.pos.y = player.size.y // 2 | |
player.move = v.vector(0, 0, 0) | |
player.motor = v.vector(0, 0, 0) | |
player.lift = v.vector(0, 0, 0) | |
player.gravity = v.vector(0, -1, 0) * Game.mass_player * Game.g | |
player.ring = v.vector(0,0,0) | |
player.shadow_body = v.box(pos=v.vector(0,0,0), size=v.vector(2,0,0.25), axis=v.vector(1,0,0), color=v.vector(0.2,0,0), opacity=0.5) | |
player.shadow_wing = v.box(pos=v.vector(0.5,0,0), size=v.vector(5,0,0.25), axis=v.vector(1,0,0), color=v.vector(0.2,0,0), opacity=0.5) | |
player.shadow_wing.rotate(angle=v.radians(90), axis=v.vector(0,1,0)) | |
#print("player size:", player.size) | |
return player | |
def f(x, z): | |
"""returns y value for a given x and z""" | |
# ----- landing strip ------ | |
if -15 < x < 30: | |
if -15 < z < 15: | |
return 0 | |
# ---- outside world ----- | |
if x < -Game.world or x > Game.world or z < - Game.world or z > Game.world: | |
return 1 | |
# ----- rest of the world ------ | |
t = 0.1 | |
#return 0.7+0.5*v.sin(10*x)*v.cos(10*z)*v.sin(5*t) | |
return 0.7 + 0.5 * v.sin(.1 * x) * v.cos(0.1 * z) * v.sin(5 * t) | |
# static objects | |
def create_world(): | |
"""puts diverse objects into static_list""" | |
# fence post | |
middle = 0 | |
h = Game.max_depth * 2 | |
Game.static_list.append(v.box(pos=v.vector(-Game.world, middle, -Game.world), size=v.vector(1.5,h,1.5))) | |
Game.static_list.append(v.box(pos=v.vector(-Game.world, middle, Game.world),size=v.vector(1.5,h,1.5))) | |
Game.static_list.append(v.box(pos=v.vector(Game.world, middle, -Game.world),size=v.vector(1.5,h,1.5))) | |
Game.static_list.append(v.box(pos=v.vector(Game.world, middle, Game.world),size=v.vector(1.5,h,1.5))) | |
# fence | |
Game.static_list.append(v.cylinder(pos=v.vector(-Game.world,1,Game.world), size=v.vector(2*Game.world,0.1,0.1), color=v.vector(0,1,0))) | |
Game.static_list.append(v.cylinder(pos=v.vector(-Game.world,1,-Game.world), size=v.vector(2*Game.world,0.1,0.1), color=v.vector(0,1,0))) | |
Game.static_list.append(v.cylinder(pos=v.vector(-Game.world,1,Game.world), size=v.vector(2*Game.world,0.1,0.1), axis=v.vector(0,0,-1), color=v.vector(0,1,0))) | |
Game.static_list.append(v.cylinder(pos=v.vector(Game.world,1,Game.world), size=v.vector(2*Game.world,0.1,0.1), axis=v.vector(0,0,-1), color=v.vector(0,1,0))) | |
# ground texture | |
#Game.static_list.append(v.box( | |
# pos=v.vector(0,-0.01,0), | |
# size=v.vector(Game.world*2,0.01,Game.world*2), | |
# color=v.vector(0.8,0.3,0.0), | |
# texture=v.textures.stucco, | |
# opacity = 0.2, | |
# )) | |
Game.vlist = [] | |
parts = 10 | |
#Game.max_depth = -10 | |
for z in v.arange(-Game.world, Game.world+1,Game.world/parts ): | |
li = [] | |
for x in v.arange(-Game.world, Game.world+1,Game.world/parts ): | |
#y= random.uniform(max_depth,0) | |
y = f(x,z) * Game.max_depth | |
li.append(v.vertex(pos=v.vec(x, y, z), | |
color=v.vector(0,y/Game.max_depth,0), | |
normal=v.vec(0,1,0) | |
)) | |
# visible dot for each vertex | |
#v.box(pos=v.vector(x,y,z), | |
# size=v.vector(0.2,0.2,0.2), | |
# color=v.vector(0.5,0.5,0.5), | |
# ) | |
#v.arrow(pos=v.vector(x,0,z), | |
# axis=v.vector(0,y,0), | |
# shaftwidth=1) | |
Game.vlist.append(li) | |
for z in range(parts*2): | |
for x in range(parts*2): | |
Game.static_list.append( | |
v.quad(v0 = Game.vlist[z][x], | |
v1 = Game.vlist[z][x+1], | |
v2 = Game.vlist[z+1][x+1], | |
v3 = Game.vlist[z+1][x], | |
) | |
) | |
#Game.static_list.append( | |
# v.quad( | |
# v0=v.vertex(pos=v.vec(-Game.world, 0, -Game.world)), | |
# v1=v.vertex(pos=v.vec(-Game.world, 12.2, Game.world)), | |
# v2=v.vertex(pos=v.vec(Game.world, -5, Game.world)), | |
# v3=v.vertex(pos=v.vec(Game.world, 4, -Game.world)), | |
# texture=v.textures.stucco, | |
# ), | |
# | |
# ) | |
# rings to fly through | |
for _ in range(5): | |
Game.ring_list.append(create_ring()) | |
update_rings() | |
Game.static_list.append(create_sun()) | |
#Game.static_list.append(create_cross()) | |
for _ in range(4): | |
create_building() | |
for _ in range(5): | |
create_flak() | |
for _ in range(14): | |
create_tank() | |
#for t in Game.tank_list: | |
# v.attach_arrow(t, "up", color=v.vector(1,1,1)) | |
def create_building(): | |
"""create a box for bomb practice (a house)""" | |
height = random.uniform(1,15) | |
x = random.uniform(-Game.world, Game.world) | |
z = random.uniform(-Game.world, Game.world) | |
y = f(x,z) * Game.max_depth | |
box = v.box(pos= v.vector(x,y + height/2,z), | |
size= v.vector(random.uniform(1,9), height , random.uniform(1,5), ), | |
axis= v.vector(random.random(), 0, random.random() ), | |
color=v.vector(0.7,0.4,0.1), | |
) | |
box.hitpoints = 800 | |
box.age = 0 | |
Game.target_list.append(box) | |
def create_bomb(shooter): | |
#b = v.simple_sphere(pos=v.vector(shooter.pos.x, shooter.pos.y+5, shooter.pos.z), | |
#color=v.vector(0.2, 0.2, 0.2), | |
#radius=0.2,) | |
b = v.cylinder(pos=v.vector(shooter.pos.x, shooter.pos.y, shooter.pos.z), | |
color= v.vector(0.2,0.2,0.2), axis = v.norm(shooter.axis)*2, radius=0.35 ) | |
b.move = v.vector(shooter.move.x, shooter.move.y, shooter.move.z) | |
shooter.block_bomb_until = shooter.age + Game.cooldown_bomb | |
b.fresh = True | |
Game.bomb_list.append(b) | |
def create_explosion(pos, max_age=0.4, hit=False): | |
e = v.simple_sphere(pos=pos, | |
radius = 0.001, | |
color=v.vector(1,1,0)) | |
e.age = 0 | |
e.max_age = max_age | |
e.hit = hit | |
#e.start_radius = start_radius | |
Game.explosion_list.append(e) | |
def update_hud(): | |
Game.hud.text = f"score: {Game.player1.points} hp: {Game.player1.hitpoints} engine: {(Game.player1.power/Game.max_power)*100:.0f}% mode: {Game.player1.modus} y: {Game.player1.pos.y:.1f} ground:{f(Game.player1.pos.x, Game.player1.pos.z)*Game.max_depth:.1f} hog: {Game.player1.pos.y - f(Game.player1.pos.x, Game.player1.pos.z)*Game.max_depth:.1f} distance to next ring: {v.mag(Game.ring_distance):.2f} " | |
def create_particle(pos, color=None): | |
if color is None: | |
color = v.vector(random.random(), random.random(), random.random()) | |
size = random.random() * 0.1 + 0.01 | |
p = v.box(pos=pos, size=v.vector(size,size,size), color=color, axis=v.vector.random()) | |
p.max_age = random.random() + 0.1 | |
p.age = 0 | |
p.move = v.vector.random() | |
p.move *= 10 | |
Game.particle_list.append(p) | |
def create_rocket(shooter, error=30.5): | |
if shooter == Game.player1: | |
c = v.vector(1, 0.3, 0.3) | |
shooter.block_rocket_until = shooter.age + Game.cooldown_rocket | |
b = v.cylinder(size=v.vector(2, 0.3, 0.3), axis=v.vector(1, 0, 0), color=c) | |
shooter.block_rocket_until = shooter.age + Game.cooldown_rocket | |
b.shooter = shooter | |
b.axis = shooter.axis | |
b.pos = v.vector(shooter.pos.x, shooter.pos.y, shooter.pos.z) | |
b.age = 0 | |
b.max_age = 2.6 | |
#b.fresh = True | |
b.error = error | |
b.move = v.vector(shooter.move.x, shooter.move.y, shooter.move.z) # v.vector(shooter.move.x, shooter.move.y, shooter.move.z) | |
xerror = random.uniform(-error, error) | |
yerror = random.uniform(-error, error) | |
b.move.rotate(v.radians(xerror), axis=v.vector(0,1,0)) | |
b.move.rotate(v.radians(yerror), axis=v.vector(1,0,0)) | |
Game.rocket_list.append(b) | |
def create_bullet(shooter, error=0.025): | |
if shooter == Game.player1: | |
c = v.vector(1,0,0) | |
shooter.block_gun_until = shooter.age + Game.cooldown_gun | |
else: | |
c = v.vector(0.8,0.8,0) | |
shooter.block_gun_until = shooter.age + Game.cooldown_flak | |
b = v.cylinder(size=v.vector(1, 0.1, 0.1), axis=v.vector(1, 0, 0), color=c) | |
b.shooter = shooter | |
b.axis = shooter.axis | |
b.pos = shooter.pos | |
b.age = 0 | |
b.max_age = 5.5 | |
b.fresh = True | |
b.error = error | |
b.move = shooter.move | |
Game.bullet_list.append(b) | |
def rotate_plane(player): | |
"""rotate smoke emitters at the plane's wings """ | |
pos1 = v.vector(player.pos.x, player.pos.y, player.pos.z) | |
# pos=v.vector(0.7,0,1), | |
pos1 += player.axis.norm() * 0.7 | |
pos2 = pos1 + v.cross(player.axis, player.up) | |
pos3 = pos1 - v.cross(player.axis, player.up) | |
return pos2, pos3 | |
def fly(): | |
ground_here = f(Game.player1.pos.x, Game.player1.pos.z) * Game.max_depth | |
if (Game.player1.pos.y - Game.radius_player) >= ground_here: | |
Game.player1.modus = "fly" | |
Game.player1.gravity = v.vector(0, -1, 0) * Game.g * Game.mass_player * Game.dt | |
if (Game.player1.pos.y - ground_here) < (2 * Game.radius_player): | |
for _ in range(5): | |
create_particle(Game.player1.pos , color=v.vector(0.1, 0.1, 0.1)) | |
#print("flying...") | |
elif (Game.player1.pos.y - Game.radius_player) < ground_here: | |
# dirt particles? | |
Game.player1.pos.y = ground_here + Game.radius_player | |
Game.player1.gravity = v.vector(0, 0, 0) | |
# Game.player1.gravity = v.vector(0,0,0) | |
if Game.player1.axis.y < 0: | |
Game.player1.power = 0 # turn engine off | |
# if Game.player1.modus == "fly": | |
# for _ in range(50): | |
# print("particle!") | |
# create_particle(Game.player1.pos + v.vector(0, 2, 0), color=v.vector(0.1, 0.1, 0.1)) | |
Game.player1.modus = "ground" | |
#else: | |
# Game.player1.modus = "ground" | |
#if Game.player1.modus == "ground": | |
Game.player1.motor = Game.player1.power * Game.dt * Game.player1.axis.norm() | |
# gravitation | |
# gravity = 9.81 * dt * v.vector(0,-1,0) #player1.up.norm() # v.vector(0,-1,0) # player1.up.norm() #TODO ABSOLUTE GRAVITY | |
# -------- lift ------ | |
# a = nase vom flugzeug | |
# b = move vom flugzeug | |
# print("comp b.a", b.axis.comp(a.axis)) | |
# p = v.arrow(pos=v.vector(0, 0, 0), axis=v.proj(b.axis, a.axis), shaftwidth=0.1, color=v.vector(0.5, 0, 0.5)) | |
#Game.player1.lift = Game.lift_factor * Game.player1.power * Game.dt * Game.player1.up.norm() | |
if Game.player1.move.comp(Game.player1.axis) > 0: | |
# Auftrieb findet statt | |
Game.player1.lift = v.mag(v.proj(Game.player1.move, Game.player1.axis)) * Game.player1.up.norm() * Game.dt * Game.lift_factor | |
else: | |
# stall | |
Game.player1.lift = v.vector(0,0,0) | |
Game.player1.move += Game.player1.motor + Game.player1.lift | |
# drag | |
drag = Game.player1.move.mag2 * Game.drag_player * -Game.player1.move.norm() | |
Game.player1.move += drag | |
# flugzeug position update | |
#position_old = v.vector(player1.pos.x, player1.pos.y, player1.pos.z) | |
Game.player1.pos_old = v.vector(Game.player1.pos.x, Game.player1.pos.y, Game.player1.pos.z) | |
Game.player1.pos += Game.player1.move | |
#if player1.pos.y < 0 and position_old.y >= 0: | |
# player1.power = 0 | |
# positionslichter update | |
Game.smoke1.pos += Game.player1.move | |
Game.smoke2.pos += Game.player1.move | |
#if Game.player1.pos.y < Game.player1.size.y / 2: | |
# Game.player1.pos.y = Game.player1.size.y / 2 | |
# Game.smoke1.pos.y = Game.player1.size.y / 2 | |
# Game.smoke2.pos.y = Game.player1.size.y / 2 | |
#elif Game.player1.pos.y >= Game.player1.size.y / 2: | |
if Game.player1.modus == "fly": | |
Game.player1.move += Game.player1.gravity | |
# update camera axis | |
#Game.scene1.forward = Game.player1.axis | |
# update shadow | |
hog = v.vector(Game.player1.pos.x, f(Game.player1.pos.x, Game.player1.pos.z) * Game.max_depth, Game.player1.pos.z) | |
#hog_old = v.vector(Game.player1.pos_old.x, f(Game.player1.pos_old.x, Game.player1.pos_old.z) * Game.max_depth, Game.player1.pos_old.z) | |
#diff = hog - hog_old | |
Game.player1.shadow_body.axis = v.vector(Game.player1.axis.x, 0 , Game.player1.axis.z) | |
Game.player1.shadow_wing.axis = v.vector(Game.player1.axis.x, 0, Game.player1.axis.z).rotate(angle=v.radians(90), axis=Game.player1.shadow_wing.up) | |
Game.player1.shadow_body.pos = v.vector(Game.player1.pos.x, hog.y+1, Game.player1.pos.z) | |
Game.player1.shadow_wing.pos = Game.player1.pos + v.norm(Game.player1.axis) * 0.25 | |
Game.player1.shadow_wing.pos.y = hog.y + 1 | |
#Game.player1.shadow_body.axis.y = diff.y | |
#Game.player1.shadow_wing.axis.y = diff.y | |
def update_rockets(): | |
for rocket in Game.rocket_list: | |
#if rocket.fresh: | |
# rocket.move += (v.norm(rocket.axis) + v.vector.random() * rocket.error) * Game.dt | |
# rocket.fresh = False | |
#rocket.move += Game.g * Game.mass_rocket * v.vector(0,-1,0) * Game.dt | |
if rocket.age < Game.rocket_fuel: | |
rocket.move += v.norm(rocket.axis) * Game.rocket_power * Game.dt | |
rocket.pos += rocket.move | |
rocket.age += Game.dt | |
ground_here = f(rocket.pos.x, rocket.pos.z) * Game.max_depth | |
if rocket.pos.y <= ground_here or rocket.age > rocket.max_age: | |
create_explosion(pos=rocket.pos, max_age=1.2 ) | |
rocket.visible = False | |
rocket.delete() | |
Game.rocket_list = [r for r in Game.rocket_list if r.visible] | |
def update_bullets(): | |
for bullet in Game.bullet_list: | |
if bullet.fresh: | |
bullet.move += (v.norm(bullet.axis) + v.vector.random() * bullet.error) * Game.cannon_power * Game.dt | |
bullet.fresh = False | |
bullet.move += Game.g * Game.mass_bullet * v.vector(0,-1,0) | |
# drag = bullet.move.mag2 * 5.515 * -bullet.move.norm() | |
#bullet.move += drag | |
bullet.pos += bullet.move * Game.dt | |
bullet.age += Game.dt | |
# collision detection bullet <-> target | |
if bullet.shooter == Game.player1: | |
for target in Game.target_list: | |
distance = bullet.pos - target.pos | |
if abs(distance.x) < target.size.x / 2: | |
if abs(distance.y) < target.size.y / 2: | |
if abs(distance.z) < target.size.z / 2: | |
# explosion | |
create_explosion(pos=bullet.pos, hit=True) | |
Game.player1.points += 1 | |
# hud.text = f"points: {player1.points} engine power: {player1.power:.2f}" | |
# update_hud() | |
target.hitpoints -= 2 # damage of bullet | |
#bullet.age = bullet.max_age | |
bullet.visible = False | |
bullet.delete() | |
else: | |
# ---- flak bullet, target is the player ! ----- | |
target = Game.player1 | |
distance = bullet.pos - target.pos | |
if v.mag(distance) < Game.flak_crit_distance: | |
target.hitpoints -= 1 | |
create_explosion(bullet.pos, hit=False) | |
#bullet.age = bullet.max_age | |
bullet.visible = False | |
bullet.delete() | |
ground_here = f(bullet.pos.x, bullet.pos.z) * Game.max_depth | |
if bullet.pos.y <= ground_here: | |
# bullet.age = 1+ bullet.max_age | |
create_explosion(pos=bullet.pos) | |
#bullet.age = bullet.max_age | |
bullet.visible = False | |
bullet.delete() | |
if bullet.age > bullet.max_age: | |
bullet.visible = False | |
bullet.delete() | |
Game.bullet_list = [b for b in Game.bullet_list if b.visible] | |
def update_rings(): | |
for index, r in enumerate(Game.ring_list): | |
if index == Game.ring_index: | |
r.color = v.vector(0,0,1) # blue | |
else: | |
r.color = v.vector(1,1,1) # white | |
def update_flak_barrels(): | |
for b in Game.flak_barrel_list: | |
b.age += Game.dt | |
distance = Game.player1.pos - b.pos | |
b.axis = v.norm(distance) * 3 | |
if b.flak.hitpoints > 0 and v.mag(distance) < Game.flak_range and b.age > b.block_gun_until: | |
create_bullet(b) | |
def update_bombs(): | |
for b in Game.bomb_list: | |
gravity = Game.g * Game.mass_bomb * v.vector(0,-1,0) | |
#print("b.move", b.move, "move:", move) | |
b.move += gravity | |
#b.move += 0.0181 * dt * v.vector(0, -1, 0).norm() | |
b.pos += b.move * Game.dt | |
# --- collision detection bomb -> target -- | |
for target in Game.target_list: | |
distance = b.pos - target.pos | |
if abs(distance.x) < target.size.x / 2: | |
if abs(distance.y) < target.size.y / 2: | |
if abs(distance.z) < target.size.z / 2: | |
# explosion | |
create_explosion(pos=b.pos, hit=True, max_age=7) | |
Game.player1.points += 1 | |
# hud.text = f"points: {player1.points} engine power: {player1.power:.2f}" | |
# update_hud() | |
target.hitpoints -= 10 | |
# b.age = b.max_age # AUSKOMMENTIEREN! | |
b.visible = False | |
b.delete() | |
ground_here = f(b.pos.x, b.pos.z) * Game.max_depth | |
if b.pos.y < ground_here: | |
b.visible = False | |
b.delete() | |
create_explosion(b.pos) | |
#explosion_list.append(create_flash) | |
Game.bomb_list = [b for b in Game.bomb_list if b.visible] | |
def update_explosions(): | |
# explosion animation | |
for e in Game.explosion_list: | |
e.age += Game.dt | |
e.radius = 0.01 + e.age * 1.1 | |
if e.age < e.max_age: | |
white = 0.8 + random.random() * 0.2 | |
if e.hit: | |
e.color = v.vector(white, white, 0) | |
else: | |
e.color = v.vector(white, white, white) | |
else: | |
e.visible = False | |
e.delete() | |
Game.explosion_list = [e for e in Game.explosion_list if e.visible] | |
def update_particles(): | |
# particle movement | |
for p in Game.particle_list: | |
p.age += Game.dt | |
p.move += Game.g * Game.mass_particle * v.vector(0,-1,0) | |
p.pos += p.move * Game.dt | |
if p.pos.y < 0: | |
p.age = p.max_age | |
if p.age >= p.max_age: | |
p.visible = False | |
p.delete() | |
Game.particle_list = [p for p in Game.particle_list if p.visible] | |
def update_tanks(): | |
# tank movement | |
for t in Game.tank_list: | |
if t.hitpoints > 0: | |
old_pos = v.vector(t.pos.x, t.pos.y, t.pos.z) | |
t.pos += t.move * Game.dt | |
bounce = False | |
if t.pos.x < -Game.world: | |
t.pos.x = -Game.world | |
bounce = True | |
new_angle = -t.angle + 180 # bounce direction | |
t.rotate(angle=v.radians(new_angle - t.angle), axis=t.up) | |
t.move = t.axis.norm() * t.power | |
t.angle = new_angle | |
#t.move = v.vector(random.randint(1,20),0,random.randint(-50, 50)).norm() * t.power | |
#t.axis = t.move.norm() | |
if t.pos.x > Game.world: | |
t.pos.x = Game.world | |
bounce = True | |
new_angle = -t.angle + 180 # bounce direction | |
t.rotate(angle=v.radians(new_angle - t.angle), axis=t.up) | |
t.move = t.axis.norm() * t.power | |
t.angle = new_angle | |
if t.pos.z < -Game.world: | |
t.pos.z = -Game.world | |
bounce = True | |
new_angle = -t.angle # bounce direction | |
t.rotate(angle=v.radians(new_angle - t.angle), axis=t.up) | |
t.move = t.axis.norm() * t.power | |
t.angle = new_angle | |
if t.pos.z > Game.world: | |
t.pos.z = Game.world | |
bounce = True | |
new_angle = -t.angle # bounce direction | |
t.rotate(angle=v.radians(new_angle - t.angle), axis=t.up) | |
t.move = t.axis.norm() * t.power | |
t.angle = new_angle | |
# ----- over ground ------ | |
ground_here = f(t.pos.x, t.pos.z) * Game.max_depth | |
#t.hy.y = ground_here | |
t.pos.y = ground_here + t.size.y / 2 | |
# update tank axis | |
if not bounce: | |
t.axis = t.pos - old_pos | |
#return tank_list | |
def slider_dt(s): | |
#print("slider1 is now:", s.value) | |
Game.dt = s.value | |
Game.label_dt.text = f"{Game.dt:.4f}" | |
def slider_lift(s): | |
Game.lift_factor = s.value | |
Game.label_lift.text = f"{Game.lift_factor:.4f}" | |
def slider_ring_center_distance(s): | |
"""how close the player must fly to the center of a ring to proceed to next ring""" | |
Game.ring_center_distance = s.value | |
Game.label_ring_center_distance.text = f"{Game.ring_center_distance:.1f}" | |
def slider_rotation(s): | |
"""how fast the plane rotates around its axis""" | |
Game.rotation = s.value | |
Game.label_rotation.text = f"{Game.rotation:.1f}" | |
def slider_delay(s): | |
"""time delay of the camera flying behind the player """ | |
Game.camera_delay = s.value | |
Game.label_delay.text = f"{Game.camera_delay:.2f}" | |
def create_widgets(): | |
Game.scene1.append_to_title(" keys: engine: 1=full 2=more 3=less 4=off. flight controls: WASDQE gun: Space bomb: Ctrl") | |
Game.scene1.append_to_title(" or use first joystick") | |
Game.scene1.append_to_caption("rotation speed: ") | |
v.slider(bind=slider_rotation, min=1, max=200, step=0.1, value=Game.rotation) | |
Game.label_rotation = v.wtext(text=f"{Game.rotation}") | |
Game.scene1.append_to_caption(Game.label_rotation) | |
Game.scene1.append_to_caption('\n\n') | |
Game.scene1.append_to_caption("camera delay [seconds]:") | |
v.slider(bind=slider_delay, min=0, max=5, step=0.01, value=Game.camera_delay) | |
Game.label_delay = v.wtext(text=f"{Game.camera_delay:.2f}") | |
Game.scene1.append_to_caption(Game.label_delay) | |
Game.scene1.append_to_caption('\n\n') | |
Game.scene1.append_to_caption("ring_center_distance:") | |
v.slider(bind= slider_ring_center_distance, min=0.2, max=15.0, step=0.1, value=Game.ring_center_distance) | |
Game.label_ring_center_distance = v.wtext(text=f"{Game.ring_center_distance:.1f}") | |
Game.scene1.append_to_caption(Game.label_ring_center_distance) | |
Game.scene1.append_to_caption('\n\n') | |
Game.scene1.append_to_caption("dt (delta time) in [seconds]:") | |
v.slider(bind=slider_dt, min=0.0001, max=0.01, step=0.00001, value=Game.dt) | |
Game.label_dt = v.wtext(text=f"{Game.dt:.4f}") | |
Game.scene1.append_to_caption(Game.label_dt) | |
Game.scene1.append_to_caption('\n\n') | |
Game.scene1.append_to_caption("lift_factor (force up vs. force forward):") | |
v.slider(bind=slider_lift, min=0.0, max=200.0, step=0.1, value=Game.lift_factor) | |
Game.label_lift = v.wtext(text=f"{Game.lift_factor:.4f}") | |
Game.scene1.append_to_caption(Game.label_lift) | |
Game.scene1.append_to_caption('\n\n') | |
def main(): | |
# Initialize the joysticks. | |
pygame.init() | |
joystick_count = pygame.joystick.get_count() | |
for i in range(joystick_count): | |
joystick = pygame.joystick.Joystick(i) | |
joystick.init() | |
#joystick = pygame.joystick.Joystick(0) | |
#joystick.init() | |
create_widgets() | |
# horst spielt mit Camera | |
Game.scene1.center= v.vector(0,0,0) | |
#scene1.autoscale=False | |
Game.scene1.camera.pos = v.vector(0,0,-1) | |
Game.player1 = create_player() | |
#Game.scene1.camera.follow(Game.player1) | |
Game.hud = v.label(pixel_pos=True, | |
pos=v.vec(5,15,0), | |
text=f"points: {Game.player1.points}", | |
#hud.text = f"points: {player1.points} engine power: {player1.power:.2f}" | |
color=v.vector(1,1,0), | |
align="left", | |
opacity=0, | |
box=False, | |
) | |
Game.smoke1 = v.simple_sphere(pos=v.vector(0.7,0,1), | |
size=v.vector(0.25,0.25,0.25), | |
color=v.vector(0,1,0), # rechts grün ) | |
make_trail=True, | |
trail_type="points", | |
interval=15, | |
retain=50, | |
trail_color=v.vector(0,1,0), | |
) | |
Game.smoke2 = v.simple_sphere(pos=v.vector(0.7,0,-1), | |
size=v.vector(0.25,0.25,0.25), | |
color=v.vector(1,0,0), # links rot) | |
make_trail=True, | |
trail_type="points", | |
interval=15, | |
retain=50, | |
trail_color=v.vector(1,0,0), | |
) | |
create_world() # put stuff into static_list | |
# -------------- movement ------------- | |
#age = 0 | |
Game.ring_index = 0 | |
Game.my_ring = Game.ring_list[Game.ring_index] | |
Game.disc= v.cylinder(pos=Game.my_ring.pos, axis=Game.my_ring.axis, radius=Game.ring_center_distance/2, length=0.1, color=v.vector(1,0,0)) | |
Game.ring_distance = Game.player1.pos - Game.my_ring.pos | |
a7 = v.attach_arrow(Game.player1, "ring", scale=55, shaftwidth=0.2, color=v.color.blue) | |
#a8 = v.attach_arrow(Game.player1, "axis", scale=100, color=v.color.white) | |
camera_zoom = 1.0 | |
camera_x_angle = 0.0 | |
camera_y_angle = 0.0 | |
camera_change = False | |
while True: | |
v.rate(200) | |
#age += Game.dt | |
#gravity = v.vector(0, -1, 0) * Game.g_player * Game.dt | |
Game.player1.age += Game.dt | |
# player bewegung | |
# player1.pos += player1.power * dt * player1.axis.norm() | |
fly() # player1 | |
# ------update camera --- | |
# this is the same as follow player1 | |
#Game.scene1.camera.pos = Game.player1.pos + v.norm( | |
# v.vector(Game.player1.axis.x, Game.player1.axis.y, Game.player1.axis.z)) * -9 + v.vector(0, 5, 0) | |
ray = v.norm(Game.player1.axis) * 10 | |
new_pos = Game.player1.pos - ray + v.vector(0,5,0) | |
f_value = f(new_pos.x, new_pos.z) * Game.max_depth | |
height_over_ground = new_pos.y - f_value | |
if height_over_ground < 5: | |
new_pos.y += 5 - height_over_ground | |
Game.scene1.camera.pos = new_pos | |
Game.camera_history.append(new_pos) | |
Game.scene1.camera.pos = Game.camera_history[0] | |
while len(Game.camera_history) > Game.camera_delay / Game.dt: | |
Game.scene1.camera.pos = Game.camera_history.pop(0) | |
caxis = v.norm(Game.player1.pos - Game.scene1.camera.pos) * 10 | |
if camera_x_angle != 0: | |
caxis = v.rotate(caxis, angle=v.radians(camera_x_angle), axis=v.vector(0,1,0)) | |
# ---- too confusing for the human eye ---- | |
#if camera_y_angle != 0: | |
# caxis = v.rotate(caxis, angle=v.radians(camera_y_angle), axis=v.vector(v.cross(caxis, v.vector(0,1,0)))) | |
Game.scene1.camera.pos = Game.player1.pos - caxis | |
Game.scene1.camera.axis = caxis | |
#Game.scene1.camera.pos = new_pos | |
#Game.scene1.camera.axis = v.norm(Game.player1.pos - Game.scene1.camera.pos) * 10 | |
# ---- ring control ----- | |
Game.ring_distance = Game.player1.pos - Game.my_ring.pos | |
if v.mag(Game.ring_distance) < Game.ring_center_distance: | |
if Game.ring_index == len(Game.ring_list) - 1: | |
Game.ring_index = 0 | |
else: | |
Game.ring_index += 1 | |
Game.my_ring = Game.ring_list[Game.ring_index] | |
Game.disc.visible = False | |
Game.disc.delete() | |
Game.disc = v.cylinder(pos=Game.my_ring.pos, axis=Game.my_ring.axis, radius=0.5, length=0.1, color=v.vector(1,0,0)) | |
update_rings() | |
Game.player1.points += 100 | |
# confetti for player | |
for _ in range(100): | |
create_particle(Game.player1.pos) | |
rdiff = Game.my_ring.pos - Game.player1.pos | |
Game.player1.ring = v.norm(rdiff) * 0.05 | |
#print(rdiff, v.mag(rdiff), v.norm(rdiff), v.mag(v.norm(rdiff))) | |
#Game.player1.ring = v.norm(Game.ring_list[Game.ring_index].pos - Game.player1.pos) * 3 | |
update_hud() | |
# --- event handler | |
# k = keysdown() # a list of keys that are down | |
keys = v.keysdown() | |
for char in "wasdqe,.": | |
if char in keys: | |
if ('q' in keys or "," in keys) and not ('e' in keys or "." in keys): | |
Game.player1.rotate(angle=v.radians(Game.rotation) * Game.dt, axis=Game.player1.up) | |
# smoke1.axis, smoke2.axis = player1.axis.norm()*0.1, player1.axis.norm()*0.1 | |
if ('e' in keys or "." in keys) and not ('q' in keys or "," in keys): | |
Game.player1.rotate(angle=v.radians(-Game.rotation) * Game.dt, axis=Game.player1.up) | |
if "s" in keys and not "w" in keys: | |
Game.player1.rotate(angle=v.radians(Game.rotation) * Game.dt, | |
axis=v.cross(Game.player1.axis, Game.player1.up)) | |
if "w" in keys and not "s" in keys: | |
Game.player1.rotate(angle=v.radians(-Game.rotation) * Game.dt, | |
axis=v.cross(Game.player1.axis, Game.player1.up)) | |
if "d" in keys and not "a" in keys: | |
Game.player1.rotate(angle=v.radians(Game.rotation) * Game.dt, | |
axis=Game.player1.axis) # axis=v.vector(1, 0, 0), ) | |
if "a" in keys and not "d" in keys: | |
Game.player1.rotate(angle=v.radians(-Game.rotation) * Game.dt, | |
axis=Game.player1.axis) # axis=v.vector(1, 0, 0), ) | |
# whatever rotation, update the somke emitters: | |
Game.smoke1.pos, Game.smoke2.pos = rotate_plane(Game.player1) | |
#smoke1.axis, smoke2.axis = player1.axis.norm() * 0.1, player1.axis.norm() * 0.1 | |
#if "p" in keys: | |
# create_particle(Game.player1.pos) | |
# ---- update sprites ---- | |
update_bullets() | |
update_bombs() | |
update_rockets() | |
update_explosions() | |
update_particles() | |
update_tanks() | |
update_flak_barrels() | |
# ---------- joystick --------- | |
# see joystick module in pygame documentation | |
# ------ necessary! without pygame event.get(), joystick events are not pulled ---- | |
for event in pygame.event.get(): # User did something. | |
if event.type == pygame.QUIT: # If user clicked close. | |
pass # done = True # Flag that we are done so we exit this loop. | |
#elif event.type == pygame.JOYBUTTONDOWN: | |
# print("Joystick button pressed.") | |
#elif event.type == pygame.JOYBUTTONUP: | |
# print("Joystick button released.") | |
if joystick_count > 0: | |
joystick = pygame.joystick.Joystick(0) | |
else: | |
joystick = None | |
if " " in keys or (joystick is not None and joystick.get_button(5)): | |
# ---------fire forward gun ---------- | |
if Game.player1.age > Game.player1.block_gun_until: | |
create_bullet(shooter=Game.player1, ) | |
if "ctrl" in keys or (joystick is not None and joystick.get_button(4)): | |
# -------- drop bomb -------------- | |
#if Game.player1.age > Game.player1.block_bomb_until: | |
# create_bomb(shooter=Game.player1) | |
if Game.player1.age > Game.player1.block_rocket_until: | |
create_rocket(shooter=Game.player1) | |
# print("rocket created") | |
#else: | |
# print("rocket blocked") | |
if "1" in keys or (joystick is not None and joystick.get_button(0)): | |
print("1 pressed") | |
Game.player1.power = Game.max_power | |
elif "2" in keys or (joystick is not None and joystick.get_axis(1) < -0.1): | |
Game.player1.power += 0.01 | |
Game.player1.power = min(Game.max_power, Game.player1.power) | |
elif "3" in keys or (joystick is not None and joystick.get_axis(1) > 0.1): | |
Game.player1.power -= 0.01 | |
Game.player1.power = max(Game.min_power, Game.player1.power) | |
elif "4" in keys: | |
Game.player1.power = 0 | |
if "c" in keys or (joystick and joystick.get_button(1)): | |
# --- reset camera --- | |
camera_zoom = 1.0 | |
camera_x_angle = 0.0 | |
camera_y_angle = 0.0 | |
if joystick is not None: | |
# flight control | |
if joystick.get_axis(0) != 0 or joystick.get_axis(2) != 0 or joystick.get_axis(3) != 0: | |
# get_axis(<number of axis>) is a float value from -1 to +1, 0 at neutral position | |
if joystick.get_axis(0) != 0: | |
# --------- joystick rudder (yaw) left/right ---------------- | |
Game.player1.rotate(angle=v.radians(Game.rotation * -joystick.get_axis(0)) * Game.dt, | |
axis=Game.player1.up) | |
if joystick.get_axis(2) != 0: | |
# -------- joystick roll left/right ------------------- | |
Game.player1.rotate(angle=v.radians(Game.rotation * joystick.get_axis(2)) * Game.dt, | |
axis=Game.player1.axis) # axis=v.vector(1, 0, 0), ) | |
if joystick.get_axis(3) != 0: | |
# -------- joystick pitch up/down ------------------- | |
# get_axis(3) is a float value from -1 to +1, 0 at neutral position | |
Game.player1.rotate(angle=v.radians(Game.rotation * joystick.get_axis(3)) * Game.dt, | |
axis=v.cross(Game.player1.axis, Game.player1.up)) | |
# in any rotation event, update the smoke emitters position: | |
Game.smoke1.pos, Game.smoke2.pos = rotate_plane(Game.player1) | |
# camera control | |
if joystick.get_hat(0)[0] == -1: | |
camera_x_angle -= 0.25 | |
camera_change = True | |
elif joystick.get_hat(0)[0] == 1: | |
camera_x_angle += 0.25 | |
camera_change = True | |
#if joystick.get_hat(0)[1] == -1: | |
# camera_y_angle -= 0.25 | |
# camera_change = True | |
#elif joystick.get_hat(0)[1] == 1: | |
# camera_y_angle += 0.25 | |
# camera_change = True | |
if __name__ == "__main__": | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment