Oct-20-2018, 09:26 PM
I am writing a simple side scrolling game in the style of the old Scramble arcade game, except with lousy graphics! I have a background composed of ground objects, which are blue rectangles of varying height. Atop them are either nothing, a turret (which will fire eventually!!) or a surface missile. I have used the range_to_fire code from the shipgame demo on here to check whether to launch a missile. There is a player ship (which is a simple triangle) and it can fire a laser or a missile. The player missile uses the formula for motion of a projectile (from here, as I couldn't remember them lol: https://formulas.tutorvista.com/physics/...rmula.html) As you can see I plan to use the state engine code eventually but just wanted it working first. Implementing the state engine code was pretty easy last time, and I am more in the habit of writing it with the update/collision_check/draw loop style as well now.
Currently it just draws a random background and uses randint to decide whether a pillar has nothing, a missile, or a turret.
Keys are cursor keys = move, space = laser, v = missile
So my current issues are:
1) The surface missiles launch, but leave a copy atop the pillar
2) the player missile has multiple copies as it drops down.
There are 2 files: constants.py and game_test.py:
Currently it just draws a random background and uses randint to decide whether a pillar has nothing, a missile, or a turret.
Keys are cursor keys = move, space = laser, v = missile
So my current issues are:
1) The surface missiles launch, but leave a copy atop the pillar
2) the player missile has multiple copies as it drops down.
There are 2 files: constants.py and game_test.py:
import pygame size = width, height = 600, 400 TOP = 5 LEFT = 5 BASE = 380 RIGHT = 570 # colors blue = (0,0,255) black = (0,0,0) white = (255,255,255) yellow = (238, 238, 0) red = (255,0,0) orange = (255, 128, 0) yellow1 = (255, 255, 0) green = (0, 255, 0) blue2 = (0, 0, 238) purple = (128, 0, 128) magenta3 = (205, 0, 205) peachpuff1 = (255, 218, 185) # unused at the minute LEFT_KEYS = [pygame.K_LEFT, pygame.K_z] RIGHT_KEYS = [pygame.K_RIGHT, pygame.K_x] UP_KEYS = [pygame.K_UP, pygame.K_p] DOWN_KEYS = [pygame.K_DOWN, pygame.K_l]
import pygame from pygame.locals import * from random import randint import sys, os, math from constants import * from state_test import States pygame.init() pygame.display.set_caption("Shooter") screen = pygame.display.set_mode(size) #pygame.key.set_repeat(10, 50) clock = pygame.time.Clock() class Game: #(States): def __init__(self): #States.__init__(self) self.next = 'title' self.screen = screen self.level = Background() self.ship = Ship(20,30) self.scroll_timer = 3 def run(self): done = False while not done: dt = clock.tick(60)/1000.0 self.ship.update(dt) if self.ship.laser.firing: self.ship.laser.update() #for missile in self.ship.missiles: if self.ship.missile: if self.ship.missile.launched: self.ship.missile.update() for missile in self.level.missiles: if self.player_in_range(missile, self.ship): missile.launched = True if missile.launched: missile.update() self.scroll_timer -= 1 if self.scroll_timer == 0: self.scroll_timer = 3 self.level.display_rect.x += 2 for bg in self.level.ground: bg.rect.x -= 2 for turret in self.level.turrets: turret.rect.x -= 2 for missile in self.level.missiles: missile.rect.x -= 2 self.collision_check() self.draw(screen) for event in pygame.event.get(): if event.type == pygame.QUIT: done = True if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: sys.exit() def collision_check(self): for bg in self.level.ground: if self.ship.rect.colliderect(bg.rect): print "ship hit background" if self.ship.laser.firing: if self.ship.laser.rect.colliderect(bg.rect): print "laser hit background" self.ship.laser.reset() if self.ship.laser.firing: for turret in self.level.turrets: if self.ship.laser.rect.colliderect(turret.rect): print "laser hit turret" self.ship.laser.reset() turret.alive = False def draw(self, surf): surf.fill((0,0,0)) surf.blit(self.level, (0,0), self.level.display_rect) self.ship.draw(surf) if self.ship.laser.firing: self.ship.laser.draw(surf) #for missile in self.ship.missiles: if self.ship.missile: if self.ship.missile.launched: self.ship.missile.draw(surf) for missile in self.level.missiles: if missile.launched: missile.draw(surf) pygame.display.flip() def player_in_range(self, missile, player): try: offset_x = missile.rect.x - player.rect.x offset_y = missile.rect.y - player.rect.y d = int(math.degrees(math.atan(offset_x / offset_y))) except ZeroDivisionError: #player is above enemy return False #if player is within 15 degrees of enemy if math.fabs(d) <= 15: print "above" return True else: return False class Ship: def __init__(self, x = 0, y = 0): self.dx = 300 self.dy = 300 self.rect = pygame.Rect(x,y,30,20) self.laser = Laser(x, y) self.missiles = [] self.missile = None def update(self, dt): keys = pygame.key.get_pressed() if keys[K_SPACE]: self.laser.firing = True self.laser.rect.x = self.rect.x+30 self.laser.rect.y = self.rect.y+15 if keys[K_v]: #m = PlayerMissile(self.rect.x, self.rect.y) #m.launched = True #self.missiles.append(m) self.missile = PlayerMissile(self.rect.x, self.rect.y) self.missile.launched = True #self.missiles.append(m) if keys[pygame.K_LEFT]: if self.rect.x > TOP: self.laser.firing = False self.rect.x -= self.dx * dt self.laser.rect.x = self.rect.x #+30 self.laser.ex = self.rect.x + 5 if keys[pygame.K_RIGHT]: if self.rect.x < RIGHT: self.laser.firing = False self.rect.x += self.dx * dt self.laser.rect.x = self.rect.x #+30 self.laser.ex = self.rect.x + 5 if keys[pygame.K_UP]: if self.rect.y > LEFT: self.laser.firing = False self.rect.y -= self.dy * dt self.laser.rect.y = self.rect.y #+15 if keys[pygame.K_DOWN]: if self.rect.y < BASE: self.laser.firing = False self.rect.y += self.dy * dt self.laser.rect.y = self.rect.y #+15 def draw(self, surf): pygame.draw.polygon(surf, white, [[self.rect.x,self.rect.y], [self.rect.x+30, self.rect.y+15], [self.rect.x, self.rect.y+20]], 5) class Laser: def __init__(self, x = 0, y = 0): self.ex = x + 5 self.speed = 20 self.rect = pygame.Rect(x, y, 5, 2) self.max_len = 600 - x self.firing = False def update(self): if self.firing: if self.ex < self.max_len - self.speed: self.ex += self.speed self.rect.width = self.ex-self.rect.x else: self.reset() def reset(self): self.firing = False self.ex = self.rect.x+5 self.rect.width = self.ex-self.rect.x def draw(self, surf): pygame.draw.line(surf, (255,0,255), (self.rect.x, self.rect.y), (self.ex, self.rect.y)) class Turret: def __init__(self, x=0, y=0): self.cx = x+15 self.cy = y+10 self.direction = LEFT self.rect = pygame.Rect(x, y, 30, 30) self.alive = True def draw(self, surf): pygame.draw.line(surf, yellow, (self.rect.x, self.rect.y), (self.cx, self.cy), 4) if self.alive: pygame.draw.arc(surf, red, self.rect, 0, 3.14, 10) else: pygame.draw.arc(surf, yellow, self.rect, 0, 3.14, 10) class SurfaceMissile: def __init__(self, x=0, y=0): self.rect = pygame.Rect(x,y,10,30) self.alive = True self.launched = False def update(self): if self.alive: self.rect.y-= 2 def draw(self, surf): pygame.draw.rect(surf, orange, self.rect) class PlayerMissile: def __init__(self, x=0, y=0): self.rect = pygame.Rect(x,y,20,20) self.alive = True self.launched = False self.sx = 6 self.sy = 0 self.time = 0 self.g = 2.0 def update(self): if self.alive and self.launched: self.time += 1 self.rect.x += (self.time * self.sx) self.rect.y += (self.g/2 * self.time**2) def draw(self, surf): pygame.draw.rect(surf, purple, self.rect) class Ground: def __init__(self, x=0, y=0, height=40, color=blue): self.width = 40 self.height = height self.rect = pygame.Rect(x, y, self.width, self.height) self.turret = None self.missile = None if randint(0,10) > 7: self.turret = Turret(x+5, y-15) if not self.turret: if randint(0,10) > 5: self.missile = SurfaceMissile(x+5, y-30) def update(self, amt): self.rect.x -= amt def draw(self, surf): if self.turret: self.turret.draw(surf) if self.missile and not self.missile.launched: self.missile.draw(surf) pygame.draw.rect(surf, blue, self.rect) class Background(pygame.Surface): def __init__(self): super(Background, self).__init__((6000, 400)) self.display_rect = pygame.Rect(0,0,600,400) self.ground = [] self.turrets = [] self.missiles = [] for c in range(5): g = Ground(c*40, 400-40, 40) self.ground.append(g) g.draw(self) for c in range(5, 130): height = randint(20, 200) g = Ground(c*40, 400-height, height) #c*40, 400-height, height) self.ground.append(g) g.draw(self) if g.turret: self.turrets.append(g.turret) if g.missile: self.missiles.append(g.missile) if __name__== "__main__": g = Game() g.run() pygame.quit() sys.exit()