From e00473b6fce0efbd8f9c31dd416b0afaf5fdaefb Mon Sep 17 00:00:00 2001 From: nathanestill Date: Mon, 5 Mar 2018 19:01:14 -0500 Subject: [PATCH 01/45] adding project proposal markdown --- ProjectProposal.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 ProjectProposal.md diff --git a/ProjectProposal.md b/ProjectProposal.md new file mode 100644 index 00000000..90d3867d --- /dev/null +++ b/ProjectProposal.md @@ -0,0 +1,15 @@ +### Main Idea +The main idea is to create the game "Asteroids". We will explore classes and the pygame library and generate a playable game at the end. Our MVP is having a controllable rocket ship and asteroids that move around and can be shot. Our strectch goal is adding the UFOs. + +### Learning Goals +Corey: To learn how user-game interactions work as well as UI. +Nathan: To learn how the pygame library works, and explore its functions. + +### Libraries +We plan to use mostly pygame for our project, and also random and math. We don't think we will need any other libraries for this project. + +### Mid-Project Check-in +We will make an arena and a a player that shoots. + +### Biggest Risks +Underestimating the amount of time it will take to complete the game and other tasks. From 43f8fb05c66f025acbdfa44c16eb93e9f4dd7d41 Mon Sep 17 00:00:00 2001 From: Corey Date: Mon, 5 Mar 2018 19:07:37 -0500 Subject: [PATCH 02/45] Added a document of things to keep in mind --- keepInMind.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 keepInMind.md diff --git a/keepInMind.md b/keepInMind.md new file mode 100644 index 00000000..03be4ac3 --- /dev/null +++ b/keepInMind.md @@ -0,0 +1,45 @@ +# Things to keep in mind when programming game + +### Objects +1. Player + * Needs to receive movement + * Needs to shoot projectile +2. Arena + * Doesn't actually end. Loops on itself (boundless but finite) +3. HUD + * High score and # of lives left +4. Projectile +5. Asteroid + * Small, Medium, and Large +6. UFO + * Small, and Large + +### Notes +1. Asteroids spawn + * Asteroids kill all + * Except for themselves + * Float through each other +2. Player can shoot self + * Careful about spawning. Don't want to spawn into an asteroid +3. Asteroid speed + * Gets faster after breakup +4. Number of asteroids/level??? +5. Projectile + * Travels ~3/4 of map length +6. Collision! + * UFO wins against player + * Player and asteroid lose together + * UFO and asteroid lose together +7. BIG UFO + * Travels from one side to the other + * Down diagonally then up until out of play space +8. Smol UFO + * One side to other in straight line + +### Points! +Large asteroid = 20 +Medium asteroid = 50 +Smol asteroid = 100 +BIG UFO = 200 +smol UFO = 1,000 +Life +1 after 10,000 From 6dd5a2cb5038c445c7b3c0e47fa6d4a70b7e631e Mon Sep 17 00:00:00 2001 From: Corey Date: Mon, 5 Mar 2018 19:18:29 -0500 Subject: [PATCH 03/45] Updated things to keep in mind --- keepInMind.md | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/keepInMind.md b/keepInMind.md index 03be4ac3..181bbb60 100644 --- a/keepInMind.md +++ b/keepInMind.md @@ -1,45 +1,46 @@ # Things to keep in mind when programming game +@author Corey Cochran-Lepiz & Nathan Estill ### Objects 1. Player - * Needs to receive movement - * Needs to shoot projectile + * Needs to receive movement + * Needs to shoot projectile 2. Arena - * Doesn't actually end. Loops on itself (boundless but finite) + * Doesn't actually end. Loops on itself (boundless but finite) 3. HUD - * High score and # of lives left + * High score and # of lives left 4. Projectile 5. Asteroid - * Small, Medium, and Large + * Small, Medium, and Large 6. UFO - * Small, and Large + * Small, and Large ### Notes 1. Asteroids spawn - * Asteroids kill all - * Except for themselves - * Float through each other + * Asteroids kill all + * Except for themselves + * Float through each other 2. Player can shoot self - * Careful about spawning. Don't want to spawn into an asteroid + * Careful about spawning. Don't want to spawn into an asteroid 3. Asteroid speed - * Gets faster after breakup + * Gets faster after breakup 4. Number of asteroids/level??? 5. Projectile - * Travels ~3/4 of map length + * Travels ~3/4 of map length 6. Collision! - * UFO wins against player - * Player and asteroid lose together - * UFO and asteroid lose together + * UFO wins against player + * Player and asteroid lose together + * UFO and asteroid lose together 7. BIG UFO - * Travels from one side to the other - * Down diagonally then up until out of play space + * Travels from one side to the other + * Down diagonally then up until out of play space 8. Smol UFO - * One side to other in straight line + * One side to other in straight line ### Points! -Large asteroid = 20 -Medium asteroid = 50 -Smol asteroid = 100 -BIG UFO = 200 -smol UFO = 1,000 -Life +1 after 10,000 +Large asteroid = 20 +Medium asteroid = 50 +Smol asteroid = 100 +BIG UFO = 200 +smol UFO = 1,000 +Life +1 after 10,000 From ea5e7196998af77462127b00b4965d6db11c76bc Mon Sep 17 00:00:00 2001 From: nathanestill Date: Tue, 6 Mar 2018 15:28:35 -0500 Subject: [PATCH 04/45] Adding Base Asteroid file contains a simple program that shows the screen and the asteroid on it. Asteroid currently pretty much sucks right now. You need the picture to run it btw. --- Asteroid.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Asteroid.py diff --git a/Asteroid.py b/Asteroid.py new file mode 100644 index 00000000..1237bf01 --- /dev/null +++ b/Asteroid.py @@ -0,0 +1,12 @@ +import pygame +pygame.init() +gameDisplay = pygame.display.set_mode((800,600)) +Astroid = pygame.image.load('Astroid.png').convert() +gameDisplay.blit(Astroid,(400,300)) +pygame.display.update() +running = True +while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False +pygame.quit() From 9f29142979ad7902b7b0670c2d217a329e20bd26 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Tue, 6 Mar 2018 15:30:15 -0500 Subject: [PATCH 05/45] adding Asteroid picture --- Asteroid.png | Bin 0 -> 6107 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Asteroid.png diff --git a/Asteroid.png b/Asteroid.png new file mode 100644 index 0000000000000000000000000000000000000000..d636372503f89393589906b50b40da2e66a72d95 GIT binary patch literal 6107 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 Date: Wed, 7 Mar 2018 11:58:28 -0500 Subject: [PATCH 06/45] adding Asteroids and Going back and forth --- Asteroid.png | Bin 6107 -> 2122 bytes Asteroid.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/Asteroid.png b/Asteroid.png index d636372503f89393589906b50b40da2e66a72d95..9b574e60d144e5f4b0f4daf1cd0d59f489af2af1 100644 GIT binary patch delta 1278 zcmVtHt%?c_Bj#~xnu z(ktJ=CTCXKYeiB;y_V%uuY;}4q?Ff=B#LltOF&<1Z}YXW4m4gB>(t*_(CU0i$e1M< zJyfbO#XzfpmE=cB0V~Vzx5AHNnn#`dSc#qrvss=#t6=r)aON^E86;{G3 zRg<7n#>#&=hm>;2$~xVawn=IKi2MXG&O`wvfLaF^J30A^&wx=B4V4=0`>0nFsc8F!b8cJ4YvBm&PYqmq9 z3c=Ev?T{I=z@iGlq6)!c$O4NhWXNL3q6)#H3fq5T8CVQiR3TVYAy`x)Ll#38RS1?A z7DHC)js+G~2o_Zc7DE<87FfBP%#Z~ZRmhOVkj0P%7FAfeV}YfEC1?d!axAJ4EUJ(p ziy>=6n-8>F8EbpPP5a7>y^UADi)Cl~3*7RvF9qS-w)T5zU*xv;PCETt0ylb9yHatf zSCxPJI=6Tgx(s%?SK*s;=ciWiTIO|LHShdh znpYF7IS;IDtY&z%!n)~Y-LUR>b;P>t)zj+Y4`gGk5nUj%-dH2F{0P?YuWe)XyBAoK z9t)_#K(_%aiUpLf+t9PXT2h5*fwiUz$9R8&R-n^>6?iOog;t=;fE7S^jaJ~{9IOD= z2ebkLU1{ogq}9m3a9?DJ67m_Ja4OY zA@Ofu1>#v(tt)AN2P+USdTQO-u$1O1>$`ttvN>*faQxX-M+^kbgf;Pw$b8rn%#M}I&uZ9ZB^Jt z3#yQfn=iQH6h9yVk;#>S=+Mp$aQ%ft4knVp?D&slr5B<_WO; zR?Zm3wG6Cs9V>;Ffi?S$K7myNEv4s|(^EBC&w6&2OB3r%i`8Bt>>!uke65}1QhYl- z#U=VCe}qeS(c}P^@)Xf-F7fHKy0& z)m#lXwrQT`s=V=Vc5cPDmM{1|wDR{b##ikpxSD*XZSxLWYH(bFap>6vE>29{!PV(3 z-rHQgj^e$?)%5)EYg`?#h`7qt^b(*;Tz&6byuihEi+%y_hz;&j=dNZS16QW|xv&aw zf#v7I%Fo5<9^k^t&xMtriy}r0aAD==`t^?oY&=|aEI$`k0WPqjT!8qwzQW<>!otr5 ogr5rqf*=TjAP9mW2!c?KAFBm7KaeUFm;e9(07*qoM6N<$g4fPy(EtDd delta 5294 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 a=YR&X$0%ju-1p9c#8Oq%R49{s8T=3IK*-Jj diff --git a/Asteroid.py b/Asteroid.py index 1237bf01..00e085f7 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -1,9 +1,78 @@ import pygame +from pygame.locals import * +import time +import math +import random +class Asteroid(): + def __init__(self,x,y,speed,direction): + self.x = x + self.y = y + self.speed = speed + self.direction = direction + #self.image = pygame.image.load('Asteroid.png').convert() + #self.w, self.h = self.image.get_size() + def update(self,gameDisplay): + width, height = gameDisplay.get_size() + self.x = self.x + (self.speed * math.cos(self.direction)) + self.y = self.y + (self.speed * math.sin(self.direction)) + if(self.x >= width): + self.x = 0 - self.w + elif(self.x <= 0 - self.w): + self.x = width + if(self.y >= height): + self.y = 0 - self.h + elif(self.y <= 0 - self.h): + self.y = height + gameDisplay.blit(self.image,(self.x,self.y)) +class LargeAsteroid(Asteroid): + def __init__(self,x,y,speed,direction): + self.image = pygame.image.load('Asteroid.png').convert() + self.w,self.h = self.image.get_size() + super().__init__(x,y,speed,direction) +class MediumAsteroid(Asteroid): + def __init__(self,x,y,speed,direction): + self.image = pygame.image.load('Asteroid.png').convert() + self.w,self.h = self.image.get_size() + self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) + self.w,self.h = self.image.get_size() + super().__init__(x,y,speed,direction) +class SmallAsteroid(Asteroid): + def __init__(self,x,y,speed,direction): + self.image = pygame.image.load('Asteroid.png').convert() + self.w,self.h = self.image.get_size() + self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) + self.w,self.h = self.image.get_size() + super().__init__(x,y,speed,direction) + +def spawnAsteroids(numberOfAsteroids,gameDisplay): + width, height = gameDisplay.get_size() + listOfAsteroids = [] + for i in numberOfAsteroids: + side = random.randint(1,4) + if(side == 1): + x = random.randint(0,200) + y = random.randint(0,height) + elif(side == 2): + x = random.randint(0,width) + y = random.randint(0,200) + elif(side == 3): + x = random.randint(width-200,width) + y = random.randint(0,height) + elif(side == 4): + x = random.randint(0,width) + y = random.randint(height-200,height) + random + listOfAsteroids.append(LargeAsteroid) pygame.init() gameDisplay = pygame.display.set_mode((800,600)) -Astroid = pygame.image.load('Astroid.png').convert() -gameDisplay.blit(Astroid,(400,300)) -pygame.display.update() +Asteroid1 = SmallAsteroid(200,300,4,math.pi / 4) +BlackScreen = pygame.image.load('BlackScreen.jpg') +gameDisplay.blit(BlackScreen,(0,0)) +for i in range(800): + gameDisplay.blit(BlackScreen,(0,0)) + Asteroid1.update(gameDisplay) + pygame.display.update() + pygame.time.delay(20) running = True while running: for event in pygame.event.get(): From 0e3a95a4a96710385ccca76552fad49eaaf10075 Mon Sep 17 00:00:00 2001 From: Corey Date: Wed, 7 Mar 2018 11:58:56 -0500 Subject: [PATCH 07/45] Begin file for interface Add class for ship Add interface for player (not done) --- interface.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ keepInMind.md | 1 + spa.png | Bin 0 -> 23380 bytes 3 files changed, 75 insertions(+) create mode 100644 interface.py create mode 100644 spa.png diff --git a/interface.py b/interface.py new file mode 100644 index 00000000..754c057e --- /dev/null +++ b/interface.py @@ -0,0 +1,74 @@ +""" +Asteroids via Pygame + +@authors coreyacl & nathanestill + +""" + +import pygame +import math + +pygame.init() + +display_width = 1000 +display_height = 800 + +gameDisplay = pygame.display.set_mode((display_width,display_height)) +pygame.display.set_caption("Asteroids") + +black = (0,0,0) +white = (255,255,255) + +clock = pygame.time.Clock() +crashed = False +shipImg = pygame.image.load('spa.png') + +class Ship(): + x_speed = 0 + y_speed = 0 + def __init__(self,x,y,angle,img): + self.angle = angle + self.x = x + self.y = y + self.image = img + def move(self): + self.x_speed += math.cos(math.radians(self.angle))*2 + self.y_speed += math.sin(math.radians(self.angle))*2 + + def rotate(self,posNeg): + self.image = pygame.transform.rotate(self.image,5*posNeg) + self.angle += posNeg*5 + + def update(self): + self.x += self.x_speed + self.y += self.y_speed + gameDisplay.blit(self.image,(self.x,self.y)) + + +shipX = (display_width * .5) +shipY = (display_height * .5) + +ship = Ship(shipX,shipY,315,shipImg) + +while not crashed: + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + crashed = True + #print(event) + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_UP: + ship.move() + if event.key == pygame.K_LEFT: + ship.rotate(1) + + gameDisplay.fill(white) + + ship.update() + + pygame.display.update() + clock.tick(60) + +pygame.quit() +quit() diff --git a/keepInMind.md b/keepInMind.md index 181bbb60..71e619f3 100644 --- a/keepInMind.md +++ b/keepInMind.md @@ -10,6 +10,7 @@ 3. HUD * High score and # of lives left 4. Projectile + * Limited to short burst 5. Asteroid * Small, Medium, and Large 6. UFO diff --git a/spa.png b/spa.png new file mode 100644 index 0000000000000000000000000000000000000000..ed41878044aad66421d12bbdb03c1d753350b035 GIT binary patch literal 23380 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 Date: Wed, 7 Mar 2018 11:59:02 -0500 Subject: [PATCH 08/45] adding BlackScreen --- BlackScreen.jpg | Bin 0 -> 6652 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 BlackScreen.jpg diff --git a/BlackScreen.jpg b/BlackScreen.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9e66a686d276debf2737c048311d18fee445ebbe GIT binary patch literal 6652 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 literal 0 HcmV?d00001 From d050675eb3945aa05f76ba0d15e185380b7cd92c Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 7 Mar 2018 12:26:48 -0500 Subject: [PATCH 09/45] Added spawning of multiple asteroids Still need to make sure that when running through the asteroids to destroy, to add them afterwords --- Asteroid.py | 103 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index 00e085f7..7210f4c4 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -9,68 +9,93 @@ def __init__(self,x,y,speed,direction): self.y = y self.speed = speed self.direction = direction - #self.image = pygame.image.load('Asteroid.png').convert() - #self.w, self.h = self.image.get_size() + self.image = pygame.image.load('Asteroid.png').convert() + self.image.set_colorkey((0,0,0)) + self.w, self.h = self.image.get_size() + self.destroyed = False def update(self,gameDisplay): - width, height = gameDisplay.get_size() - self.x = self.x + (self.speed * math.cos(self.direction)) - self.y = self.y + (self.speed * math.sin(self.direction)) - if(self.x >= width): - self.x = 0 - self.w - elif(self.x <= 0 - self.w): - self.x = width - if(self.y >= height): - self.y = 0 - self.h - elif(self.y <= 0 - self.h): - self.y = height - gameDisplay.blit(self.image,(self.x,self.y)) + if(not self.destroyed): + width, height = gameDisplay.get_size() + self.x = self.x + (self.speed * math.cos(self.direction)) + self.y = self.y + (self.speed * math.sin(self.direction)) + if(self.x >= width): + self.x = 0 - self.w + elif(self.x <= 0 - self.w): + self.x = width + if(self.y >= height): + self.y = 0 - self.h + elif(self.y <= 0 - self.h): + self.y = height + gameDisplay.blit(self.image,(self.x,self.y)) class LargeAsteroid(Asteroid): def __init__(self,x,y,speed,direction): - self.image = pygame.image.load('Asteroid.png').convert() - self.w,self.h = self.image.get_size() super().__init__(x,y,speed,direction) -class MediumAsteroid(Asteroid): - def __init__(self,x,y,speed,direction): - self.image = pygame.image.load('Asteroid.png').convert() - self.w,self.h = self.image.get_size() self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) self.w,self.h = self.image.get_size() - super().__init__(x,y,speed,direction) -class SmallAsteroid(Asteroid): + def destroy(self): + self.destroyed = True + MedAster = [] + for i in range(2): + MedAster.append(MediumAsteroid(self.x,self.y,self.speed*2,random.uniform(0,2*math.pi))) + return MedAster +class MediumAsteroid(Asteroid): def __init__(self,x,y,speed,direction): - self.image = pygame.image.load('Asteroid.png').convert() - self.w,self.h = self.image.get_size() + super().__init__(x,y,speed,direction) self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) self.w,self.h = self.image.get_size() +class SmallAsteroid(Asteroid): + def __init__(self,x,y,speed,direction): super().__init__(x,y,speed,direction) + self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) + self.w,self.h = self.image.get_size() -def spawnAsteroids(numberOfAsteroids,gameDisplay): +def spawnAsteroids(numberOfAsteroids,gameDisplay,speed): width, height = gameDisplay.get_size() listOfAsteroids = [] - for i in numberOfAsteroids: + sampleAsteroid = LargeAsteroid(0,0,0,0) + smallArea = 100 + for i in range(numberOfAsteroids): side = random.randint(1,4) if(side == 1): - x = random.randint(0,200) - y = random.randint(0,height) + x = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.h // 2,height - sampleAsteroid.h // 2) elif(side == 2): - x = random.randint(0,width) - y = random.randint(0,200) + x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) elif(side == 3): - x = random.randint(width-200,width) - y = random.randint(0,height) + x = random.randint(width-smallArea - sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint( -sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) elif(side == 4): - x = random.randint(0,width) - y = random.randint(height-200,height) - random - listOfAsteroids.append(LargeAsteroid) + x = random.randint( -sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(height-smallArea - sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) + direction = random.uniform(0,math.pi * 2) + listOfAsteroids.append(LargeAsteroid(x,y,speed,direction)) + return listOfAsteroids + pygame.init() gameDisplay = pygame.display.set_mode((800,600)) -Asteroid1 = SmallAsteroid(200,300,4,math.pi / 4) +#Asteroid1 = SmallAsteroid(200,300,4,math.pi / 4) +Asteroids = spawnAsteroids(6,gameDisplay,2) BlackScreen = pygame.image.load('BlackScreen.jpg') gameDisplay.blit(BlackScreen,(0,0)) -for i in range(800): +for j in Asteroids: + j.update(gameDisplay) +pygame.display.update() +pygame.time.delay(3000) +for i in range(400): + gameDisplay.blit(BlackScreen,(0,0)) + #Asteroid1.update(gameDisplay) + for j in Asteroids: + j.update(gameDisplay) + pygame.display.update() + pygame.time.delay(20) +for k in Asteroids: + Asteroids += k.destroy() +for i in range(400): gameDisplay.blit(BlackScreen,(0,0)) - Asteroid1.update(gameDisplay) + #Asteroid1.update(gameDisplay) + for j in Asteroids: + j.update(gameDisplay) pygame.display.update() pygame.time.delay(20) running = True From c17e415374d7508930a8889b63601b8c0e608aae Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 8 Mar 2018 18:04:34 -0500 Subject: [PATCH 10/45] Add functions for UI interaction Started to work on ship movement and drift. Working on enabling acceleration instead of just velocioty. --- interface.py | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/interface.py b/interface.py index 754c057e..ffb41b82 100644 --- a/interface.py +++ b/interface.py @@ -20,7 +20,7 @@ white = (255,255,255) clock = pygame.time.Clock() -crashed = False +running = True shipImg = pygame.image.load('spa.png') class Ship(): @@ -31,17 +31,42 @@ def __init__(self,x,y,angle,img): self.x = x self.y = y self.image = img + self.w,self.h = img.get_size() def move(self): - self.x_speed += math.cos(math.radians(self.angle))*2 - self.y_speed += math.sin(math.radians(self.angle))*2 + if math.sqrt(self.x_speed**2+self.y_speed**2) < 8: + self.x_speed += math.cos(math.radians(self.angle))*2 + self.y_speed += math.sin(math.radians(self.angle))*2 + + def drift(self): + """ + Drifts the ship to a stop. Doesn't work yet + """ + if math.sqrt(self.x_speed**2+self.y_speed**2) > 0: + self.x_speed = -self.x_speed/10 + self.y_speed = -self.y_speed/10 + else: + self.x_speed = 0 + self.y_speed = 0 def rotate(self,posNeg): self.image = pygame.transform.rotate(self.image,5*posNeg) self.angle += posNeg*5 def update(self): + width,height = gameDisplay.get_size() + self.x += self.x_speed self.y += self.y_speed + + if(self.x >= width): + self.x = 0 - self.w + elif(self.x <= 0 - self.w): + self.x = width + if(self.y >= height): + self.y = 0 - self.h + elif(self.y <= 0 - self.h): + self.y = height + gameDisplay.blit(self.image,(self.x,self.y)) @@ -50,11 +75,11 @@ def update(self): ship = Ship(shipX,shipY,315,shipImg) -while not crashed: +while running: for event in pygame.event.get(): if event.type == pygame.QUIT: - crashed = True + running = False #print(event) if event.type == pygame.KEYDOWN: @@ -62,6 +87,11 @@ def update(self): ship.move() if event.key == pygame.K_LEFT: ship.rotate(1) + if event.key == pygame.K_RIGHT: + ship.rotate(-1) + if event.type == pygame.KEYUP: + if event.key == pygame.K_UP: + ship.drift() gameDisplay.fill(white) From 59b16ba740646d8252fa3e285a66257f53e86209 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Fri, 9 Mar 2018 00:12:35 -0500 Subject: [PATCH 11/45] adding comments --- Asteroid.py | 56 ++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index 7210f4c4..8c1187d0 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -10,95 +10,95 @@ def __init__(self,x,y,speed,direction): self.speed = speed self.direction = direction self.image = pygame.image.load('Asteroid.png').convert() - self.image.set_colorkey((0,0,0)) - self.w, self.h = self.image.get_size() + self.image.set_colorkey((0,0,0)) # Sets the Asteroids Blackness to be transparent + self.w, self.h = self.image.get_size() # Gets the Asteroid's width and height self.destroyed = False def update(self,gameDisplay): - if(not self.destroyed): - width, height = gameDisplay.get_size() - self.x = self.x + (self.speed * math.cos(self.direction)) + if(not self.destroyed): # once the asteroid is destroyed, it will stop redrawing the asteroid + width, height = gameDisplay.get_size() # gets the display's width and length + self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the Asteroid's to a small change in space self.y = self.y + (self.speed * math.sin(self.direction)) - if(self.x >= width): - self.x = 0 - self.w - elif(self.x <= 0 - self.w): + if(self.x >= width): # If the asteroid's coordinate goes outside of the window, set that coordinate to the other side of the map + self.x = 0 - self.w # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) + elif(self.x <= 0 - self.w): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) self.x = width if(self.y >= height): self.y = 0 - self.h elif(self.y <= 0 - self.h): self.y = height - gameDisplay.blit(self.image,(self.x,self.y)) + gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen class LargeAsteroid(Asteroid): def __init__(self,x,y,speed,direction): super().__init__(x,y,speed,direction) - self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) + self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) # scales the asteroid to size self.w,self.h = self.image.get_size() def destroy(self): self.destroyed = True MedAster = [] for i in range(2): - MedAster.append(MediumAsteroid(self.x,self.y,self.speed*2,random.uniform(0,2*math.pi))) + MedAster.append(MediumAsteroid(self.x,self.y,self.speed*2,random.uniform(0,2*math.pi))) #makes two more medium asteroids in it's place with random directions return MedAster class MediumAsteroid(Asteroid): def __init__(self,x,y,speed,direction): super().__init__(x,y,speed,direction) - self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) + self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) # half as big as large asteroid self.w,self.h = self.image.get_size() class SmallAsteroid(Asteroid): def __init__(self,x,y,speed,direction): super().__init__(x,y,speed,direction) - self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) + self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) # half as big as large asteroid self.w,self.h = self.image.get_size() def spawnAsteroids(numberOfAsteroids,gameDisplay,speed): width, height = gameDisplay.get_size() - listOfAsteroids = [] - sampleAsteroid = LargeAsteroid(0,0,0,0) - smallArea = 100 + listOfAsteroids = [] # initializes a list of asteroids to update + sampleAsteroid = LargeAsteroid(0,0,0,0) # a sample asteroid to know where to spawn the asteroids in case we change the size later + smallArea = 100 # the area that asteroids are to spawn around the the edge for i in range(numberOfAsteroids): side = random.randint(1,4) - if(side == 1): + if(side == 1): # left side of the screen x = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) y = random.randint(-sampleAsteroid.h // 2,height - sampleAsteroid.h // 2) - elif(side == 2): + elif(side == 2): # top side of the screen x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) y = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) - elif(side == 3): + elif(side == 3): # right side of the screen x = random.randint(width-smallArea - sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) y = random.randint( -sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) - elif(side == 4): + elif(side == 4): # bottom of the screen x = random.randint( -sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) y = random.randint(height-smallArea - sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) - direction = random.uniform(0,math.pi * 2) + direction = random.uniform(0,math.pi * 2) # initiate each asteroid with a random direction listOfAsteroids.append(LargeAsteroid(x,y,speed,direction)) return listOfAsteroids pygame.init() gameDisplay = pygame.display.set_mode((800,600)) #Asteroid1 = SmallAsteroid(200,300,4,math.pi / 4) -Asteroids = spawnAsteroids(6,gameDisplay,2) -BlackScreen = pygame.image.load('BlackScreen.jpg') +Asteroids = spawnAsteroids(6,gameDisplay,2) # initiating a list of asteroids to keep track of +BlackScreen = pygame.image.load('BlackScreen.jpg') # black screen is the background gameDisplay.blit(BlackScreen,(0,0)) for j in Asteroids: - j.update(gameDisplay) + j.update(gameDisplay) # testing the many asteroids spawn in the right spot pygame.display.update() pygame.time.delay(3000) for i in range(400): gameDisplay.blit(BlackScreen,(0,0)) #Asteroid1.update(gameDisplay) for j in Asteroids: - j.update(gameDisplay) + j.update(gameDisplay) # update each asteroid pygame.display.update() pygame.time.delay(20) for k in Asteroids: - Asteroids += k.destroy() + Asteroids += k.destroy() # destroying all of the asteroids making them medium for i in range(400): gameDisplay.blit(BlackScreen,(0,0)) #Asteroid1.update(gameDisplay) for j in Asteroids: - j.update(gameDisplay) + j.update(gameDisplay) # reupdate everything pygame.display.update() pygame.time.delay(20) -running = True +running = True # for the exit of the game while running: for event in pygame.event.get(): if event.type == pygame.QUIT: From abbe146fd7b02fa1b202b5326297cec640d73b5e Mon Sep 17 00:00:00 2001 From: Corey Date: Fri, 9 Mar 2018 15:15:12 -0500 Subject: [PATCH 12/45] Fix ship movement mechanics -Drift works -Rotate works -Movement needs to be finalized -Endless region works -Added quit() function when you press 'q' --- interface.py | 86 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/interface.py b/interface.py index ffb41b82..4b828550 100644 --- a/interface.py +++ b/interface.py @@ -6,7 +6,7 @@ """ import pygame -import math +from math import cos,sin,sqrt,radians,atan pygame.init() @@ -23,38 +23,81 @@ running = True shipImg = pygame.image.load('spa.png') +def rot_center(image, angle): + """rotate an image while keeping its center and size + Found online. Very helpful + """ + + orig_rect = image.get_rect() + rot_image = pygame.transform.rotate(image, angle) + rot_rect = orig_rect.copy() + rot_rect.center = rot_image.get_rect().center + rot_image = rot_image.subsurface(rot_rect).copy() + return rot_image + class Ship(): + """Ship class! + Holds data on ship: + angle (degress) + x_speed + y_speed + x (position) + y (position) + image + drift (boolean) + + """ x_speed = 0 y_speed = 0 + drift = False def __init__(self,x,y,angle,img): + """ + Initliazes with where the ship is facing as the angle + """ self.angle = angle self.x = x self.y = y self.image = img self.w,self.h = img.get_size() def move(self): - if math.sqrt(self.x_speed**2+self.y_speed**2) < 8: - self.x_speed += math.cos(math.radians(self.angle))*2 - self.y_speed += math.sin(math.radians(self.angle))*2 - - def drift(self): - """ - Drifts the ship to a stop. Doesn't work yet + """FORWARD!!! + Moves the ship forward in the direction it's heading (its angle) """ - if math.sqrt(self.x_speed**2+self.y_speed**2) > 0: - self.x_speed = -self.x_speed/10 - self.y_speed = -self.y_speed/10 - else: - self.x_speed = 0 - self.y_speed = 0 + ship.drift = False + if sqrt(self.x_speed**2+self.y_speed**2) < 10: + self.x_speed += cos(radians(self.angle))*2 + self.y_speed += sin(radians(self.angle))*2 def rotate(self,posNeg): - self.image = pygame.transform.rotate(self.image,5*posNeg) - self.angle += posNeg*5 + """Rotates ship""" + self.image = rot_center(self.image,posNeg*35) + #self.image = pygame.transform.rotate(self.image,35*posNeg) + self.angle -= posNeg*35 + # speed = sqrt(self.x_speed**2+self.y_speed**2) + # self.x_speed = cos(radians(self.angle))*speed + # self.y_speed = sin(radians(self.angle))*speed + + def update(self): + """MAGIC + Does magic and makes the ship work. + Updates position + """ width,height = gameDisplay.get_size() - + if self.drift: + speed = sqrt(self.x_speed**2+self.y_speed**2)*.02 + theta = atan(self.y_speed/self.x_speed) + self.x_speed -= cos(theta)*speed + self.y_speed -= sin(theta)*speed + if sqrt(self.x_speed**2+self.y_speed**2) < .02: + self.x_speed = 0 + self.y_speed = 0 + self.drift = False + if sqrt(self.x_speed**2+self.y_speed**2) > 10: + self.drift = False + self.x_speed = cos(radians(self.angle)) + self.y_speed = sin(radians(self.angle)) self.x += self.x_speed self.y += self.y_speed @@ -72,7 +115,8 @@ def update(self): shipX = (display_width * .5) shipY = (display_height * .5) - +w,h = shipImg.get_size() +shipImg = pygame.transform.scale(shipImg,(int(w*.5),int(h*.5))) ship = Ship(shipX,shipY,315,shipImg) while running: @@ -80,7 +124,7 @@ def update(self): for event in pygame.event.get(): if event.type == pygame.QUIT: running = False - #print(event) + # print(event) if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: @@ -91,7 +135,9 @@ def update(self): ship.rotate(-1) if event.type == pygame.KEYUP: if event.key == pygame.K_UP: - ship.drift() + ship.drift = True + if event.key == pygame.K_q: + running = False gameDisplay.fill(white) From bf1234944e2fc5a74e64e9b1460617345eb369e0 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Fri, 9 Mar 2018 15:22:33 -0500 Subject: [PATCH 13/45] deleting black screen and adding CollectionOfAsteroids --- Asteroid.py | 132 +++++++++++++++++++++++++++++------------------- BlackScreen.jpg | Bin 6652 -> 0 bytes 2 files changed, 80 insertions(+), 52 deletions(-) delete mode 100644 BlackScreen.jpg diff --git a/Asteroid.py b/Asteroid.py index 8c1187d0..6ef0146b 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -26,81 +26,109 @@ def update(self,gameDisplay): self.y = 0 - self.h elif(self.y <= 0 - self.h): self.y = height + self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen class LargeAsteroid(Asteroid): def __init__(self,x,y,speed,direction): super().__init__(x,y,speed,direction) self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) # scales the asteroid to size self.w,self.h = self.image.get_size() + self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) def destroy(self): - self.destroyed = True - MedAster = [] - for i in range(2): - MedAster.append(MediumAsteroid(self.x,self.y,self.speed*2,random.uniform(0,2*math.pi))) #makes two more medium asteroids in it's place with random directions - return MedAster + if(not self.destroyed): + self.destroyed = True + MedAster = [] + for i in range(2): + MedAster.append(MediumAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi))) #makes two more medium asteroids in it's place with random directions + return MedAster + return None class MediumAsteroid(Asteroid): def __init__(self,x,y,speed,direction): super().__init__(x,y,speed,direction) self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) # half as big as large asteroid self.w,self.h = self.image.get_size() + self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) + def destroy(self): + if(not self.destroyed): + self.destroyed = True + SmallAster = [] + for i in range(2): + SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi))) #makes two more medium asteroids in it's place with random directions + return SmallAster + return None class SmallAsteroid(Asteroid): def __init__(self,x,y,speed,direction): super().__init__(x,y,speed,direction) self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) # half as big as large asteroid self.w,self.h = self.image.get_size() - -def spawnAsteroids(numberOfAsteroids,gameDisplay,speed): - width, height = gameDisplay.get_size() - listOfAsteroids = [] # initializes a list of asteroids to update - sampleAsteroid = LargeAsteroid(0,0,0,0) # a sample asteroid to know where to spawn the asteroids in case we change the size later - smallArea = 100 # the area that asteroids are to spawn around the the edge - for i in range(numberOfAsteroids): - side = random.randint(1,4) - if(side == 1): # left side of the screen - x = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) - y = random.randint(-sampleAsteroid.h // 2,height - sampleAsteroid.h // 2) - elif(side == 2): # top side of the screen - x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) - y = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) - elif(side == 3): # right side of the screen - x = random.randint(width-smallArea - sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) - y = random.randint( -sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) - elif(side == 4): # bottom of the screen - x = random.randint( -sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) - y = random.randint(height-smallArea - sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) - direction = random.uniform(0,math.pi * 2) # initiate each asteroid with a random direction - listOfAsteroids.append(LargeAsteroid(x,y,speed,direction)) - return listOfAsteroids - + self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) + def destroy(self): + self.destroyed = True +class CollectionOfAsteroids(): + def __init__(self,gameDisplay,speed): + self.listOfAsteroids = [] + self.gameDisplay = gameDisplay + self.speed = speed + def spawnAsteroids(self,numberOfAsteroids): + width, height = gameDisplay.get_size() + listOfAsteroids = [] # initializes a list of asteroids to update + listOfRects = [] + sampleAsteroid = LargeAsteroid(0,0,0,0) # a sample asteroid to know where to spawn the asteroids in case we change the size later + smallArea = 100 # the area that asteroids are to spawn around the the edge + for i in range(numberOfAsteroids): + side = random.randint(1,4) + if(side == 1): # left side of the screen + x = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.h // 2,height - sampleAsteroid.h // 2) + elif(side == 2): # top side of the screen + x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) + elif(side == 3): # right side of the screen + x = random.randint(width-smallArea - sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) + elif(side == 4): # bottom of the screen + x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(height-smallArea - sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) + direction = random.uniform(0,math.pi * 2) # initiate each asteroid with a random direction + listOfAsteroids.append(LargeAsteroid(x,y,self.speed,direction)) + listOfRects.append(listOfAsteroids[i].rect) + self.listOfAsteroids = listOfAsteroids + self.listOfRects = listOfRects + def updateAsteroids(self,gameDisplay): + listOfRects = [] + print(pygame.Rect.collidelistall(self.listOfRects[0],self.listOfRects)) + for i in self.listOfAsteroids: + i.update(gameDisplay) + listOfRects.append(i.rect) + self.listOfRects = listOfRects + def destroyAll(self): + sizeOfAsteroids = range(len(self.listOfAsteroids)) + for i in sizeOfAsteroids: + newAsteroid = self.listOfAsteroids[i].destroy() + if(newAsteroid != None): + self.listOfAsteroids += newAsteroid # destroying all of the asteroids making them medium + for i in sizeOfAsteroids: + self.listOfAsteroids.pop(0) pygame.init() gameDisplay = pygame.display.set_mode((800,600)) -#Asteroid1 = SmallAsteroid(200,300,4,math.pi / 4) -Asteroids = spawnAsteroids(6,gameDisplay,2) # initiating a list of asteroids to keep track of -BlackScreen = pygame.image.load('BlackScreen.jpg') # black screen is the background -gameDisplay.blit(BlackScreen,(0,0)) -for j in Asteroids: - j.update(gameDisplay) # testing the many asteroids spawn in the right spot +clock = pygame.time.Clock() +CollAster = CollectionOfAsteroids(gameDisplay,2) +CollAster.spawnAsteroids(6) # initiating a list of asteroids to keep track of +Black = (0,0,0) # black screen is the background +gameDisplay.fill(Black) +CollAster.updateAsteroids(gameDisplay) # testing the many asteroids spawn in the right spot pygame.display.update() -pygame.time.delay(3000) -for i in range(400): - gameDisplay.blit(BlackScreen,(0,0)) - #Asteroid1.update(gameDisplay) - for j in Asteroids: - j.update(gameDisplay) # update each asteroid - pygame.display.update() - pygame.time.delay(20) -for k in Asteroids: - Asteroids += k.destroy() # destroying all of the asteroids making them medium -for i in range(400): - gameDisplay.blit(BlackScreen,(0,0)) - #Asteroid1.update(gameDisplay) - for j in Asteroids: - j.update(gameDisplay) # reupdate everything - pygame.display.update() - pygame.time.delay(20) + running = True # for the exit of the game while running: + gameDisplay.fill(Black) + CollAster.updateAsteroids(gameDisplay)# update each asteroid + pygame.display.update() + clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False + if event.type == pygame.KEYUP: + if event.key == pygame.K_q: + running = False pygame.quit() diff --git a/BlackScreen.jpg b/BlackScreen.jpg deleted file mode 100644 index 9e66a686d276debf2737c048311d18fee445ebbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6652 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 From bd64cf303fea4367692e0e2238ffff90e1e5002c Mon Sep 17 00:00:00 2001 From: Corey Date: Sun, 11 Mar 2018 14:16:57 -0400 Subject: [PATCH 14/45] Modidy interface.py and add classes.py -Screen is now black -Added score for the GUI -working to make the rotate cleaner, not working -movement still doesn't work --- classes.py | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++ interface.py | 116 +++++++-------------------------------------- spa1.png | Bin 0 -> 55299 bytes 3 files changed, 149 insertions(+), 98 deletions(-) create mode 100644 classes.py create mode 100644 spa1.png diff --git a/classes.py b/classes.py new file mode 100644 index 00000000..6420be2f --- /dev/null +++ b/classes.py @@ -0,0 +1,131 @@ +import pygame +from math import cos,sin,sqrt,radians,atan + +pygame.init() + +class GUI(): + WHITE = (255,255,255) + font = pygame.font.SysFont("couriernew",32) + bx = 150 + by = 100 + + def __init__(self,gD): + self.gD = gD + + def update(self,score): + box = pygame.surface.Surface((self.bx, self.by)) + # txt_surf = self.font.render("score", True, self.WHITE) # headline + # txt_rect = txt_surf.get_rect(center=(self.bx//2, 30)) + # box.blit(txt_surf, txt_rect) + txt_surf = self.font.render(str(score), True, self.WHITE) # bottom line + txt_rect = txt_surf.get_rect(center=(self.bx//2, 40)) + box.blit(txt_surf, txt_rect) + self.gD.blit(box,(0,0)) + + + +# def rot_center(image, angle): +# """rotate an image while keeping its center and size +# Found online. Very helpful +# print(type(image)) +# """ +# orig_rect = image.get_rect() +# rot_image = pygame.transform.rotate(image, angle) +# rot_rect = orig_rect.copy() +# rot_rect.center = rot_image.get_rect().center +# rot_image = rot_image.subsurface(rot_rect).copy() +# return rot_image +def rot_center(image, angle): + """rotate a Surface, maintaining position.""" + #DOES NOT WORK + + loc = image.get_rect().center #rot_image is not defined + rot_sprite = pygame.transform.rotate(image, angle) + rot_sprite.get_rect().center = loc + return rot_sprite + +class Ship(): + """Ship class! + Holds data on ship: + angle (degress) + x_speed + y_speed + x (position) + y (position) + oImage (img) original + nImage (img) new + drift (boolean) + forward (boolean) + ro (boolean) + rdir (1 or -1) + + """ + x_speed = 0 + y_speed = 0 + drift = False + forward = False + ro = False + rdir = 0 + def __init__(self,x,y,angle,img,gD): + """ + Initliazes with where the ship is facing as the angle + """ + self.angle = angle + self.x = x + self.y = y + self.oImage = img + self.nImage = img + self.w,self.h = img.get_size() + self.gD = gD + def move(self): + """FORWARD!!! + Moves the ship forward in the direction it's heading (its angle) + """ + self.drift = False + self.x_speed += cos(radians(self.angle))*.7 + self.y_speed += sin(radians(self.angle))*.7 + # if sqrt(self.x_speed**2+self.y_speed**2) < 10: + + def rotate(self): + """Rotates ship""" + self.nImage = rot_center(self.oImage,self.rdir*3+(270-self.angle)) + self.angle -= self.rdir*3 + + def update(self): + """MAGIC + Does magic and makes the ship work. + Updates position + """ + width,height = self.gD.get_size() + speed = sqrt(self.x_speed**2+self.y_speed**2) + if speed < .02 and self.drift: + self.drift = False + self.x_speed = 0 + self.y_speed = 0 + if speed > 10: + # self.drift = False + self.x_speed = cos(radians(self.angle))*10 + self.y_speed = sin(radians(self.angle))*10 + if self.drift: + theta = atan(self.y_speed/self.x_speed) + self.x_speed -= cos(theta)*speed*.02 + self.y_speed -= sin(theta)*speed*.02 + + if self.forward: + self.move() + if self.ro: + self.rotate() + + self.y += self.y_speed + self.x += self.x_speed + + if(self.x >= width): + self.x = 0 - self.w + elif(self.x <= 0 - self.w): + self.x = width + if(self.y >= height): + self.y = 0 - self.h + elif(self.y <= 0 - self.h): + self.y = height + + self.gD.blit(self.nImage,(self.x,self.y)) diff --git a/interface.py b/interface.py index 4b828550..8ccc84b1 100644 --- a/interface.py +++ b/interface.py @@ -7,11 +7,14 @@ import pygame from math import cos,sin,sqrt,radians,atan +from classes import * + pygame.init() display_width = 1000 display_height = 800 +imgScale = .2 gameDisplay = pygame.display.set_mode((display_width,display_height)) pygame.display.set_caption("Asteroids") @@ -21,103 +24,15 @@ clock = pygame.time.Clock() running = True -shipImg = pygame.image.load('spa.png') - -def rot_center(image, angle): - """rotate an image while keeping its center and size - Found online. Very helpful - """ - - orig_rect = image.get_rect() - rot_image = pygame.transform.rotate(image, angle) - rot_rect = orig_rect.copy() - rot_rect.center = rot_image.get_rect().center - rot_image = rot_image.subsurface(rot_rect).copy() - return rot_image - -class Ship(): - """Ship class! - Holds data on ship: - angle (degress) - x_speed - y_speed - x (position) - y (position) - image - drift (boolean) - - """ - x_speed = 0 - y_speed = 0 - drift = False - def __init__(self,x,y,angle,img): - """ - Initliazes with where the ship is facing as the angle - """ - self.angle = angle - self.x = x - self.y = y - self.image = img - self.w,self.h = img.get_size() - def move(self): - """FORWARD!!! - Moves the ship forward in the direction it's heading (its angle) - """ - ship.drift = False - if sqrt(self.x_speed**2+self.y_speed**2) < 10: - self.x_speed += cos(radians(self.angle))*2 - self.y_speed += sin(radians(self.angle))*2 - - def rotate(self,posNeg): - """Rotates ship""" - self.image = rot_center(self.image,posNeg*35) - #self.image = pygame.transform.rotate(self.image,35*posNeg) - self.angle -= posNeg*35 - # speed = sqrt(self.x_speed**2+self.y_speed**2) - # self.x_speed = cos(radians(self.angle))*speed - # self.y_speed = sin(radians(self.angle))*speed - - - - def update(self): - """MAGIC - Does magic and makes the ship work. - Updates position - """ - width,height = gameDisplay.get_size() - if self.drift: - speed = sqrt(self.x_speed**2+self.y_speed**2)*.02 - theta = atan(self.y_speed/self.x_speed) - self.x_speed -= cos(theta)*speed - self.y_speed -= sin(theta)*speed - if sqrt(self.x_speed**2+self.y_speed**2) < .02: - self.x_speed = 0 - self.y_speed = 0 - self.drift = False - if sqrt(self.x_speed**2+self.y_speed**2) > 10: - self.drift = False - self.x_speed = cos(radians(self.angle)) - self.y_speed = sin(radians(self.angle)) - self.x += self.x_speed - self.y += self.y_speed - - if(self.x >= width): - self.x = 0 - self.w - elif(self.x <= 0 - self.w): - self.x = width - if(self.y >= height): - self.y = 0 - self.h - elif(self.y <= 0 - self.h): - self.y = height - - gameDisplay.blit(self.image,(self.x,self.y)) - +shipImg = pygame.image.load('spa1.png') shipX = (display_width * .5) shipY = (display_height * .5) w,h = shipImg.get_size() -shipImg = pygame.transform.scale(shipImg,(int(w*.5),int(h*.5))) -ship = Ship(shipX,shipY,315,shipImg) +shipImg = pygame.transform.scale(shipImg,(int(w*imgScale),int(h*imgScale))) +ship = Ship(shipX,shipY,270,shipImg,gameDisplay) + +gui = GUI(gameDisplay) while running: @@ -128,19 +43,24 @@ def update(self): if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: - ship.move() + ship.forward = True if event.key == pygame.K_LEFT: - ship.rotate(1) + ship.ro = True + ship.rdir = 1 if event.key == pygame.K_RIGHT: - ship.rotate(-1) + ship.ro = True + ship.rdir = -1 if event.type == pygame.KEYUP: + if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: + ship.ro = False if event.key == pygame.K_UP: ship.drift = True + ship.forward = False if event.key == pygame.K_q: running = False - gameDisplay.fill(white) - + gameDisplay.fill(black) + gui.update(150000) ship.update() pygame.display.update() diff --git a/spa1.png b/spa1.png new file mode 100644 index 0000000000000000000000000000000000000000..789fa7680600f3c68ff17d737ef00cf483c1d2b9 GIT binary patch literal 55299 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%0A0hJcENK-3rLX@?KmIkgiQg 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

ju~fu*_w?}WUqQ= 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 literal 0 HcmV?d00001 From 42697de2d3a4a80f3b4d5c3cdb52d3adefd77f65 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Sun, 11 Mar 2018 15:45:20 -0400 Subject: [PATCH 15/45] added projectile class --- Asteroid.py | 153 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 122 insertions(+), 31 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index 6ef0146b..c7723b0a 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -4,7 +4,7 @@ import math import random class Asteroid(): - def __init__(self,x,y,speed,direction): + def __init__(self,x,y,speed,direction,gameDisplay): self.x = x self.y = y self.speed = speed @@ -13,9 +13,10 @@ def __init__(self,x,y,speed,direction): self.image.set_colorkey((0,0,0)) # Sets the Asteroids Blackness to be transparent self.w, self.h = self.image.get_size() # Gets the Asteroid's width and height self.destroyed = False - def update(self,gameDisplay): + self.gameDisplay = gameDisplay + def update(self): if(not self.destroyed): # once the asteroid is destroyed, it will stop redrawing the asteroid - width, height = gameDisplay.get_size() # gets the display's width and length + width, height = self.gameDisplay.get_size() # gets the display's width and length self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the Asteroid's to a small change in space self.y = self.y + (self.speed * math.sin(self.direction)) if(self.x >= width): # If the asteroid's coordinate goes outside of the window, set that coordinate to the other side of the map @@ -26,54 +27,59 @@ def update(self,gameDisplay): self.y = 0 - self.h elif(self.y <= 0 - self.h): self.y = height - self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) - gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + pygame.draw.rect(self.gameDisplay,(255,0,0),self.rect) + self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen class LargeAsteroid(Asteroid): - def __init__(self,x,y,speed,direction): - super().__init__(x,y,speed,direction) + def __init__(self,x,y,speed,direction,gameDisplay): + super().__init__(x,y,speed,direction,gameDisplay) self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) # scales the asteroid to size self.w,self.h = self.image.get_size() - self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) + self.shrinkage = 50 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) def destroy(self): if(not self.destroyed): self.destroyed = True MedAster = [] for i in range(2): - MedAster.append(MediumAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi))) #makes two more medium asteroids in it's place with random directions + MedAster.append(MediumAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more medium asteroids in it's place with random directions return MedAster - return None + return [] class MediumAsteroid(Asteroid): - def __init__(self,x,y,speed,direction): - super().__init__(x,y,speed,direction) + def __init__(self,x,y,speed,direction,gameDisplay): + super().__init__(x,y,speed,direction,gameDisplay) self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) # half as big as large asteroid self.w,self.h = self.image.get_size() - self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) + self.shrinkage = 25 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) def destroy(self): if(not self.destroyed): self.destroyed = True SmallAster = [] for i in range(2): - SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi))) #makes two more medium asteroids in it's place with random directions + SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more medium asteroids in it's place with random directions return SmallAster - return None + return [] class SmallAsteroid(Asteroid): - def __init__(self,x,y,speed,direction): - super().__init__(x,y,speed,direction) + def __init__(self,x,y,speed,direction,gameDisplay): + super().__init__(x,y,speed,direction,gameDisplay) self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) # half as big as large asteroid self.w,self.h = self.image.get_size() - self.rect = pygame.Rect((self.x,self.y),(self.x+self.w,self.y+self.h)) + self.shrinkage = 12 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) def destroy(self): self.destroyed = True + return [] class CollectionOfAsteroids(): def __init__(self,gameDisplay,speed): self.listOfAsteroids = [] self.gameDisplay = gameDisplay self.speed = speed def spawnAsteroids(self,numberOfAsteroids): - width, height = gameDisplay.get_size() + width, height = self.gameDisplay.get_size() listOfAsteroids = [] # initializes a list of asteroids to update listOfRects = [] - sampleAsteroid = LargeAsteroid(0,0,0,0) # a sample asteroid to know where to spawn the asteroids in case we change the size later + sampleAsteroid = LargeAsteroid(0,0,0,0,self.gameDisplay) # a sample asteroid to know where to spawn the asteroids in case we change the size later smallArea = 100 # the area that asteroids are to spawn around the the edge for i in range(numberOfAsteroids): side = random.randint(1,4) @@ -90,16 +96,21 @@ def spawnAsteroids(self,numberOfAsteroids): x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) y = random.randint(height-smallArea - sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) direction = random.uniform(0,math.pi * 2) # initiate each asteroid with a random direction - listOfAsteroids.append(LargeAsteroid(x,y,self.speed,direction)) + listOfAsteroids.append(LargeAsteroid(x,y,self.speed,direction,self.gameDisplay)) listOfRects.append(listOfAsteroids[i].rect) self.listOfAsteroids = listOfAsteroids self.listOfRects = listOfRects - def updateAsteroids(self,gameDisplay): + def update(self): listOfRects = [] - print(pygame.Rect.collidelistall(self.listOfRects[0],self.listOfRects)) - for i in self.listOfAsteroids: - i.update(gameDisplay) - listOfRects.append(i.rect) + ListToDelete = [] + for i in range(len(self.listOfAsteroids)): + if(self.listOfAsteroids[i].destroyed): + ListToDelete.append(i) + else: + self.listOfAsteroids[i].update() + listOfRects.append(self.listOfAsteroids[i].rect) + for j in reversed(ListToDelete): + del self.listOfAsteroids[j] self.listOfRects = listOfRects def destroyAll(self): sizeOfAsteroids = range(len(self.listOfAsteroids)) @@ -109,21 +120,101 @@ def destroyAll(self): self.listOfAsteroids += newAsteroid # destroying all of the asteroids making them medium for i in sizeOfAsteroids: self.listOfAsteroids.pop(0) +class Projectile(): + def __init__(self,x,y,direction,gameDisplay): + size = 3 + self.x = x + self.y = y + self.w = size + self.h = size + self.speed = 10 + self.direction = direction + self.rect = ((self.x,self.y),(size,size)) + self.image = pygame.Surface((size,size)) + self.image.fill((255,255,255)) + self.gameDisplay = gameDisplay + self.destroyed = False + self.distanceTravelled = 0 + self.distanceWanted = 500 + def update(self): + if(self.distanceTravelled < self.distanceWanted): # once the asteroid is destroyed, it will stop redrawing the asteroid + width, height = self.gameDisplay.get_size() # gets the display's width and length + self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the Asteroid's to a small change in space + self.y = self.y + (self.speed * math.sin(self.direction)) + self.distanceTravelled += self.speed + if(self.x >= width): # If the asteroid's coordinate goes outside of the window, set that coordinate to the other side of the map + self.x = 0 - self.w # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) + elif(self.x <= 0 - self.w): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) + self.x = width + if(self.y >= height): + self.y = 0 - self.h + elif(self.y <= 0 - self.h): + self.y = height + self.rect = pygame.Rect((self.x,self.y),(self.w,self.h)) + pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) + self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen + else: + self.destroy() + def destroy(self): + self.destroyed = True +class CollectionOfProjectiles(): + def __init__(self,gameDisplay): + self.listOfProjectiles = [] + self.listOfRects = [] + self.gameDisplay = gameDisplay + def addProjectile(self,x,y,direction): + self.listOfProjectiles.append(Projectile(x,y,direction,self.gameDisplay)) + def update(self): + print(len(self.listOfProjectiles)) + ListToDelete = [] + for i in range(len(self.listOfProjectiles)): + if(self.listOfProjectiles[i].destroyed): + ListToDelete.append(i) + else: + self.listOfProjectiles[i].update() + for j in reversed(ListToDelete): + del self.listOfProjectiles[j] +class listOfObjects(): + def __init__(self,asteroids,proj): + self.Asteroids = asteroids + self.Projectiles = proj + def update(self): + self.Projectiles.update() + self.Asteroids.update() + print(len(self.Asteroids.listOfAsteroids),len(self.Asteroids.listOfRects)) + for i in self.Projectiles.listOfProjectiles: + collisions = i.rect.collidelist(self.Asteroids.listOfRects) + if (collisions != -1): + self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisions].destroy() + i.destroy() + + pygame.init() gameDisplay = pygame.display.set_mode((800,600)) clock = pygame.time.Clock() -CollAster = CollectionOfAsteroids(gameDisplay,2) -CollAster.spawnAsteroids(6) # initiating a list of asteroids to keep track of +numberOfAsteroids = 4 +CollAster = CollectionOfAsteroids(gameDisplay,1) +CollAster.spawnAsteroids(numberOfAsteroids) # initiating a list of asteroids to keep track of +proj = CollectionOfProjectiles(gameDisplay) +proj.addProjectile(400,300,math.pi / 4) Black = (0,0,0) # black screen is the background gameDisplay.fill(Black) -CollAster.updateAsteroids(gameDisplay) # testing the many asteroids spawn in the right spot +AllThings = listOfObjects(CollAster,proj) +AllThings.update() # testing the many asteroids spawn in the right spot pygame.display.update() - running = True # for the exit of the game +randomCounter = 0 while running: + randomCounter += 1 + if(randomCounter % 50 == 0): + AllThings.Projectiles.addProjectile(400,300,random.uniform(0,2*math.pi)) gameDisplay.fill(Black) - CollAster.updateAsteroids(gameDisplay)# update each asteroid + AllThings.update()# update each asteroid + #proj.update() pygame.display.update() + if(len(AllThings.Asteroids.listOfAsteroids) == 0): + numberOfAsteroids += 1 + AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: From 4a142b3c05b05cf7287881d2fa682ed782218a23 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Sun, 11 Mar 2018 22:20:51 -0400 Subject: [PATCH 16/45] added comments --- Asteroid.py | 62 ++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index c7723b0a..b0bbbede 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -27,16 +27,16 @@ def update(self): self.y = 0 - self.h elif(self.y <= 0 - self.h): self.y = height - self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) - pygame.draw.rect(self.gameDisplay,(255,0,0),self.rect) + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # The Rect is for the hitbox self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen + #pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) # display's the asteroid's hit box in red (for testing) class LargeAsteroid(Asteroid): def __init__(self,x,y,speed,direction,gameDisplay): super().__init__(x,y,speed,direction,gameDisplay) self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) # scales the asteroid to size self.w,self.h = self.image.get_size() self.shrinkage = 50 - self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # lessening the hitbox so the corners don't stick out def destroy(self): if(not self.destroyed): self.destroyed = True @@ -57,13 +57,13 @@ def destroy(self): self.destroyed = True SmallAster = [] for i in range(2): - SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more medium asteroids in it's place with random directions + SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more small asteroids in it's place with random directions return SmallAster return [] class SmallAsteroid(Asteroid): def __init__(self,x,y,speed,direction,gameDisplay): super().__init__(x,y,speed,direction,gameDisplay) - self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) # half as big as large asteroid + self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) # half as big as medium asteroid self.w,self.h = self.image.get_size() self.shrinkage = 12 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) @@ -78,7 +78,7 @@ def __init__(self,gameDisplay,speed): def spawnAsteroids(self,numberOfAsteroids): width, height = self.gameDisplay.get_size() listOfAsteroids = [] # initializes a list of asteroids to update - listOfRects = [] + listOfRects = [] # initializes a list of hitboxes sampleAsteroid = LargeAsteroid(0,0,0,0,self.gameDisplay) # a sample asteroid to know where to spawn the asteroids in case we change the size later smallArea = 100 # the area that asteroids are to spawn around the the edge for i in range(numberOfAsteroids): @@ -102,17 +102,17 @@ def spawnAsteroids(self,numberOfAsteroids): self.listOfRects = listOfRects def update(self): listOfRects = [] - ListToDelete = [] + ListToDelete = [] # a list that incluedes the indicies of what to delete for i in range(len(self.listOfAsteroids)): if(self.listOfAsteroids[i].destroyed): - ListToDelete.append(i) + ListToDelete.append(i) # if the asteroid is destroyed, remember the number to remove it later else: self.listOfAsteroids[i].update() listOfRects.append(self.listOfAsteroids[i].rect) - for j in reversed(ListToDelete): + for j in reversed(ListToDelete): # reversed so that it doesn't delete one and shift mid for loop. del self.listOfAsteroids[j] self.listOfRects = listOfRects - def destroyAll(self): + def destroyAll(self): # function for testing, not for the real game sizeOfAsteroids = range(len(self.listOfAsteroids)) for i in sizeOfAsteroids: newAsteroid = self.listOfAsteroids[i].destroy() @@ -135,14 +135,14 @@ def __init__(self,x,y,direction,gameDisplay): self.gameDisplay = gameDisplay self.destroyed = False self.distanceTravelled = 0 - self.distanceWanted = 500 + self.distanceWanted = 500 # the distance that the projectile travels before it is destroyed def update(self): - if(self.distanceTravelled < self.distanceWanted): # once the asteroid is destroyed, it will stop redrawing the asteroid + if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself width, height = self.gameDisplay.get_size() # gets the display's width and length - self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the Asteroid's to a small change in space + self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the speed to a small change in space self.y = self.y + (self.speed * math.sin(self.direction)) - self.distanceTravelled += self.speed - if(self.x >= width): # If the asteroid's coordinate goes outside of the window, set that coordinate to the other side of the map + self.distanceTravelled += self.speed # updates the disnance travelled + if(self.x >= width): # If the projectile's coordinate goes outside of the window, set that coordinate to the other side of the map self.x = 0 - self.w # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) elif(self.x <= 0 - self.w): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) self.x = width @@ -151,41 +151,41 @@ def update(self): elif(self.y <= 0 - self.h): self.y = height self.rect = pygame.Rect((self.x,self.y),(self.w,self.h)) - pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) - self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen + self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the pixel on the screen + #pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) # display's the projectile's hit box in green (for testing) else: - self.destroy() + self.destroy() # satisfying to right def destroy(self): self.destroyed = True class CollectionOfProjectiles(): def __init__(self,gameDisplay): - self.listOfProjectiles = [] - self.listOfRects = [] + self.listOfProjectiles = [] #initializes the projectiles + self.listOfRects = [] # initializes their hitboxes self.gameDisplay = gameDisplay def addProjectile(self,x,y,direction): - self.listOfProjectiles.append(Projectile(x,y,direction,self.gameDisplay)) + self.listOfProjectiles.append(Projectile(x,y,direction,self.gameDisplay)) # The spacebar command should call this + # with the x,y and directions of the ship (with an offset bc of the front of the ship and that the origin is top left) def update(self): - print(len(self.listOfProjectiles)) - ListToDelete = [] + ListToDelete = [] # initializes the indices of what to delete for i in range(len(self.listOfProjectiles)): if(self.listOfProjectiles[i].destroyed): - ListToDelete.append(i) + ListToDelete.append(i) # adding the index of destroyed particles to delete else: self.listOfProjectiles[i].update() for j in reversed(ListToDelete): del self.listOfProjectiles[j] class listOfObjects(): - def __init__(self,asteroids,proj): + def __init__(self,asteroids,projectiles): self.Asteroids = asteroids - self.Projectiles = proj + self.Projectiles = projectiles # contains the CollectionOfAsteroids and CollectionOfProjectiles objects def update(self): self.Projectiles.update() self.Asteroids.update() print(len(self.Asteroids.listOfAsteroids),len(self.Asteroids.listOfRects)) - for i in self.Projectiles.listOfProjectiles: - collisions = i.rect.collidelist(self.Asteroids.listOfRects) - if (collisions != -1): - self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisions].destroy() + for i in self.Projectiles.listOfProjectiles: # runs throught each projectile + collisions = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile + if (collisions != -1): # if there is a collision + self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisions].destroy() #destroy both the asteroid and the projectile. i.destroy() @@ -206,7 +206,7 @@ def update(self): randomCounter = 0 while running: randomCounter += 1 - if(randomCounter % 50 == 0): + if(randomCounter % 5 == 0): AllThings.Projectiles.addProjectile(400,300,random.uniform(0,2*math.pi)) gameDisplay.fill(Black) AllThings.update()# update each asteroid From 1c6dbdf2f4ae435e3c33d17fbc8d4a9cd41b11cd Mon Sep 17 00:00:00 2001 From: nathanestill Date: Tue, 13 Mar 2018 16:44:57 -0400 Subject: [PATCH 17/45] starting to add UFOs and added comments on most of the classes and functions --- Asteroid.py | 128 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 13 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index b0bbbede..72b637e4 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -3,7 +3,19 @@ import time import math import random + + class Asteroid(): + """ + Asteroid Class: + x - position + y - position + speed - speed of asteroid + direction - direction of asteroid + image - surface containing picture of asteroid + gameDisplay - the display to put the asteroid on + w, h - the width and height of the surface + """ def __init__(self,x,y,speed,direction,gameDisplay): self.x = x self.y = y @@ -15,6 +27,9 @@ def __init__(self,x,y,speed,direction,gameDisplay): self.destroyed = False self.gameDisplay = gameDisplay def update(self): + """ + updates the position of the asteroid and rectangle + """ if(not self.destroyed): # once the asteroid is destroyed, it will stop redrawing the asteroid width, height = self.gameDisplay.get_size() # gets the display's width and length self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the Asteroid's to a small change in space @@ -30,7 +45,14 @@ def update(self): self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # The Rect is for the hitbox self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen #pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) # display's the asteroid's hit box in red (for testing) + class LargeAsteroid(Asteroid): + + """ + subclass of the asteroid, for the starting asteroids + shrinkage - number that the rectangle hitbox shrinks by + rect - the hitbox rectangle + """ def __init__(self,x,y,speed,direction,gameDisplay): super().__init__(x,y,speed,direction,gameDisplay) self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) # scales the asteroid to size @@ -38,6 +60,9 @@ def __init__(self,x,y,speed,direction,gameDisplay): self.shrinkage = 50 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # lessening the hitbox so the corners don't stick out def destroy(self): + """ + destroys the asteroid and returns the asteroids that should take it's place. + """ if(not self.destroyed): self.destroyed = True MedAster = [] @@ -46,6 +71,11 @@ def destroy(self): return MedAster return [] class MediumAsteroid(Asteroid): + """ + subclass of the asteroid, for the second asteroid + shrinkage - number that the rectangle hitbox shrinks by + rect - the hitbox rectangle + """ def __init__(self,x,y,speed,direction,gameDisplay): super().__init__(x,y,speed,direction,gameDisplay) self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) # half as big as large asteroid @@ -53,6 +83,9 @@ def __init__(self,x,y,speed,direction,gameDisplay): self.shrinkage = 25 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) def destroy(self): + """ + destroys the asteroid and returns the asteroids that should take it's place. + """ if(not self.destroyed): self.destroyed = True SmallAster = [] @@ -61,6 +94,11 @@ def destroy(self): return SmallAster return [] class SmallAsteroid(Asteroid): + """ + subclass of the asteroid, for the last asteroid + shrinkage - number that the rectangle hitbox shrinks by + rect - the hitbox rectangle + """ def __init__(self,x,y,speed,direction,gameDisplay): super().__init__(x,y,speed,direction,gameDisplay) self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) # half as big as medium asteroid @@ -68,6 +106,9 @@ def __init__(self,x,y,speed,direction,gameDisplay): self.shrinkage = 12 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) def destroy(self): + """ + destroys the asteroid and returns nothing because it is the smallest asteroid + """ self.destroyed = True return [] class CollectionOfAsteroids(): @@ -174,6 +215,65 @@ def update(self): self.listOfProjectiles[i].update() for j in reversed(ListToDelete): del self.listOfProjectiles[j] + +class UFO(): + def __init__(self,y,FacingRight,gameDisplay): + self.y = y + self.speed = 4 + self.destroyed = False + self.image = pygame.image.load('UFO.gif').convert() + self.image.set_colorkey((0,0,0)) + self.w, self.h = self.image.get_size() + self.straight = bool(random.getrandbits(1)) + self.FacingRight = FacingRight + self.gameDisplay = gameDisplay + width, height = gameDisplay.get_size() + if(FacingRight): + self.x = -self.w + else: + self.x = width + def update(self): + width, height = self.gameDisplay.get_size() + if(self.straight == True): + if(self.FacingRight): + self.direction = 0 + else: + self.direction = math.pi + else: + if(self.FacingRight): + if((self.x + self.w / 2) < width * 1 / 4): + self.direction = 0 + elif(self.x + self.w / 2 < width / 2): + self.direction = math.pi / 4 + else: + self.direction = - math.pi / 4 + else: + if((self.x + self.w / 2) > width * 3 / 4): + self.direction = math.pi + elif(self.x + self.w / 2 > width / 2): + self.direction = 5 * math.pi / 4 + else: + self.direction = 3 * math.pi / 4 + self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the speed to a small change in space + self.y = self.y + (self.speed * math.sin(self.direction)) + if(self.x >= width): # if the UFO goes out of the screen, destroy it + self.destroyed = True + elif(self.x <= 0 - self.w): + self.destroyed = True + if(self.y >= height): # If the UFOs coordinate goes outside of the window, set that coordinate to the other side of the map + self.y = 0 - self.h # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) + elif(self.y <= 0 - self.h): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) + self.y = height + self.gameDisplay.blit(self.image,(self.x,self.y)) + def destroy(self): + self.destroyed = True +def BigUFO(UFO): + def __init__(self,y,FacingRight,gameDisplay): + super().__init__(y,FacingRight,gameDisplay) + self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) + self.w,self.h = self.image.get_size() + def shoot(self,listOfProjectiles): + listOfProjectiles.addProjectile(self.x,self.y,random.uniform(0,2*math.pi)) class listOfObjects(): def __init__(self,asteroids,projectiles): self.Asteroids = asteroids @@ -193,28 +293,30 @@ def update(self): gameDisplay = pygame.display.set_mode((800,600)) clock = pygame.time.Clock() numberOfAsteroids = 4 -CollAster = CollectionOfAsteroids(gameDisplay,1) -CollAster.spawnAsteroids(numberOfAsteroids) # initiating a list of asteroids to keep track of -proj = CollectionOfProjectiles(gameDisplay) -proj.addProjectile(400,300,math.pi / 4) +# CollAster = CollectionOfAsteroids(gameDisplay,1) +# CollAster.spawnAsteroids(numberOfAsteroids) # initiating a list of asteroids to keep track of +# proj = CollectionOfProjectiles(gameDisplay) +# proj.addProjectile(400,300,math.pi / 4) Black = (0,0,0) # black screen is the background gameDisplay.fill(Black) -AllThings = listOfObjects(CollAster,proj) -AllThings.update() # testing the many asteroids spawn in the right spot +# AllThings = listOfObjects(CollAster,proj) +# AllThings.update() # testing the many asteroids spawn in the right spot pygame.display.update() running = True # for the exit of the game randomCounter = 0 +UFO = UFO(300,True,gameDisplay) while running: - randomCounter += 1 - if(randomCounter % 5 == 0): - AllThings.Projectiles.addProjectile(400,300,random.uniform(0,2*math.pi)) + # randomCounter += 1 + # if(randomCounter % 5 == 0): + # AllThings.Projectiles.addProjectile(400,300,random.uniform(0,2*math.pi)) gameDisplay.fill(Black) - AllThings.update()# update each asteroid + # AllThings.update()# update each asteroid #proj.update() + UFO.update() pygame.display.update() - if(len(AllThings.Asteroids.listOfAsteroids) == 0): - numberOfAsteroids += 1 - AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) + # if(len(AllThings.Asteroids.listOfAsteroids) == 0): + # numberOfAsteroids += 1 + # AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: From 82502dc6e3d8143c51c2a6d2ac40248308b2e06f Mon Sep 17 00:00:00 2001 From: Corey Date: Tue, 13 Mar 2018 16:45:51 -0400 Subject: [PATCH 18/45] Finish movement -Movement works -Improved functions -Rotation is still inneftive --- classes.py | 71 ++++++++++++++++++++++++++-------------------------- interface.py | 25 ++++++++---------- 2 files changed, 46 insertions(+), 50 deletions(-) diff --git a/classes.py b/classes.py index 6420be2f..c40a194f 100644 --- a/classes.py +++ b/classes.py @@ -24,25 +24,27 @@ def update(self,score): -# def rot_center(image, angle): -# """rotate an image while keeping its center and size -# Found online. Very helpful -# print(type(image)) -# """ -# orig_rect = image.get_rect() -# rot_image = pygame.transform.rotate(image, angle) -# rot_rect = orig_rect.copy() -# rot_rect.center = rot_image.get_rect().center -# rot_image = rot_image.subsurface(rot_rect).copy() -# return rot_image def rot_center(image, angle): - """rotate a Surface, maintaining position.""" - #DOES NOT WORK - - loc = image.get_rect().center #rot_image is not defined - rot_sprite = pygame.transform.rotate(image, angle) - rot_sprite.get_rect().center = loc - return rot_sprite + """rotate an image while keeping its center and size + Found online. Very helpful + print(type(image)) + """ + orig_rect = image.get_rect() + rot_image = pygame.transform.rotate(image, angle) + rot_rect = orig_rect.copy() + rot_rect.center = rot_image.get_rect().center + rot_image = rot_image.subsurface(rot_rect).copy() + return rot_image +# def rot_center(image, angle): +# """rotate a Surface, maintaining position.""" +# #DOES NOT WORK +# +# loc = image.get_rect().center #rot_image is not defined +# rot_sprite = pygame.transform.rotate(image, angle) +# # rot_sprite.get_rect().center = loc +# rotRect = rot_sprite.get_rect() +# rotRect.center = loc +# return rot_sprite,rotRect class Ship(): """Ship class! @@ -63,9 +65,6 @@ class Ship(): x_speed = 0 y_speed = 0 drift = False - forward = False - ro = False - rdir = 0 def __init__(self,x,y,angle,img,gD): """ Initliazes with where the ship is facing as the angle @@ -77,19 +76,20 @@ def __init__(self,x,y,angle,img,gD): self.nImage = img self.w,self.h = img.get_size() self.gD = gD + self.rect = img.get_rect() def move(self): """FORWARD!!! Moves the ship forward in the direction it's heading (its angle) """ self.drift = False - self.x_speed += cos(radians(self.angle))*.7 - self.y_speed += sin(radians(self.angle))*.7 + self.x_speed += cos(radians(self.angle))*.4 + self.y_speed += sin(radians(self.angle))*.4 # if sqrt(self.x_speed**2+self.y_speed**2) < 10: - def rotate(self): + def rotate(self,posNeg): """Rotates ship""" - self.nImage = rot_center(self.oImage,self.rdir*3+(270-self.angle)) - self.angle -= self.rdir*3 + self.nImage = rot_center(self.oImage,posNeg*3+(270-self.angle)) + self.angle -= posNeg*3 def update(self): """MAGIC @@ -98,7 +98,8 @@ def update(self): """ width,height = self.gD.get_size() speed = sqrt(self.x_speed**2+self.y_speed**2) - if speed < .02 and self.drift: + # print(speed) + if speed < .08 and self.drift: self.drift = False self.x_speed = 0 self.y_speed = 0 @@ -107,14 +108,14 @@ def update(self): self.x_speed = cos(radians(self.angle))*10 self.y_speed = sin(radians(self.angle))*10 if self.drift: - theta = atan(self.y_speed/self.x_speed) - self.x_speed -= cos(theta)*speed*.02 - self.y_speed -= sin(theta)*speed*.02 - - if self.forward: - self.move() - if self.ro: - self.rotate() + #theta = atan(self.y_speed/self.x_speed) + self.x_speed *= .98 + self.y_speed *= .98 + + # if self.forward: + # self.move() + # if self.ro: + # self.rotate() self.y += self.y_speed self.x += self.x_speed diff --git a/interface.py b/interface.py index 8ccc84b1..0cbf1d2b 100644 --- a/interface.py +++ b/interface.py @@ -40,24 +40,19 @@ if event.type == pygame.QUIT: running = False # print(event) - - if event.type == pygame.KEYDOWN: - if event.key == pygame.K_UP: - ship.forward = True - if event.key == pygame.K_LEFT: - ship.ro = True - ship.rdir = 1 - if event.key == pygame.K_RIGHT: - ship.ro = True - ship.rdir = -1 if event.type == pygame.KEYUP: - if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: - ship.ro = False - if event.key == pygame.K_UP: - ship.drift = True - ship.forward = False if event.key == pygame.K_q: running = False + keys_pressed = pygame.key.get_pressed() + + if keys_pressed[pygame.K_UP]: + ship.move() + else: + ship.drift = True + if keys_pressed[pygame.K_LEFT]: + ship.rotate(1) + if keys_pressed[pygame.K_RIGHT]: + ship.rotate(-1) gameDisplay.fill(black) gui.update(150000) From 1957138d604173f96bb6feb684faa19eddf0d2ab Mon Sep 17 00:00:00 2001 From: nathanestill Date: Tue, 13 Mar 2018 21:02:15 -0400 Subject: [PATCH 19/45] finished UFO code --- Asteroid.py | 130 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 87 insertions(+), 43 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index 72b637e4..f1c46ffe 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -112,10 +112,10 @@ def destroy(self): self.destroyed = True return [] class CollectionOfAsteroids(): - def __init__(self,gameDisplay,speed): + def __init__(self,gameDisplay): self.listOfAsteroids = [] self.gameDisplay = gameDisplay - self.speed = speed + self.speed = 1 def spawnAsteroids(self,numberOfAsteroids): width, height = self.gameDisplay.get_size() listOfAsteroids = [] # initializes a list of asteroids to update @@ -142,7 +142,7 @@ def spawnAsteroids(self,numberOfAsteroids): self.listOfAsteroids = listOfAsteroids self.listOfRects = listOfRects def update(self): - listOfRects = [] + listOfRects = [] # asteroid ListToDelete = [] # a list that incluedes the indicies of what to delete for i in range(len(self.listOfAsteroids)): if(self.listOfAsteroids[i].destroyed): @@ -153,7 +153,7 @@ def update(self): for j in reversed(ListToDelete): # reversed so that it doesn't delete one and shift mid for loop. del self.listOfAsteroids[j] self.listOfRects = listOfRects - def destroyAll(self): # function for testing, not for the real game + def destroyAll(self): # function for testingasteroid, not for the real game sizeOfAsteroids = range(len(self.listOfAsteroids)) for i in sizeOfAsteroids: newAsteroid = self.listOfAsteroids[i].destroy() @@ -162,7 +162,7 @@ def destroyAll(self): # function for testing, not for the real game for i in sizeOfAsteroids: self.listOfAsteroids.pop(0) class Projectile(): - def __init__(self,x,y,direction,gameDisplay): + def __init__(self,x,y,direction,alliance,gameDisplay): size = 3 self.x = x self.y = y @@ -175,8 +175,9 @@ def __init__(self,x,y,direction,gameDisplay): self.image.fill((255,255,255)) self.gameDisplay = gameDisplay self.destroyed = False - self.distanceTravelled = 0 + self.distanceTravelled = 0 # asteroids self.distanceWanted = 500 # the distance that the projectile travels before it is destroyed + self.alliance = alliance def update(self): if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself width, height = self.gameDisplay.get_size() # gets the display's width and length @@ -200,11 +201,11 @@ def destroy(self): self.destroyed = True class CollectionOfProjectiles(): def __init__(self,gameDisplay): - self.listOfProjectiles = [] #initializes the projectiles + self.listOfProjectiles = [] #initializes the asteroidprojectiles self.listOfRects = [] # initializes their hitboxes self.gameDisplay = gameDisplay - def addProjectile(self,x,y,direction): - self.listOfProjectiles.append(Projectile(x,y,direction,self.gameDisplay)) # The spacebar command should call this + def addProjectile(self,x,y,direction,alliance): + self.listOfProjectiles.append(Projectile(x,y,direction,alliance,self.gameDisplay)) # The spacebar command should call this # with the x,y and directions of the ship (with an offset bc of the front of the ship and that the origin is top left) def update(self): ListToDelete = [] # initializes the indices of what to delete @@ -217,7 +218,7 @@ def update(self): del self.listOfProjectiles[j] class UFO(): - def __init__(self,y,FacingRight,gameDisplay): + def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.y = y self.speed = 4 self.destroyed = False @@ -228,11 +229,16 @@ def __init__(self,y,FacingRight,gameDisplay): self.FacingRight = FacingRight self.gameDisplay = gameDisplay width, height = gameDisplay.get_size() + self.counter = 0 + self.listOfProjectiles = listOfProjectiles if(FacingRight): self.x = -self.w else: self.x = width def update(self): + if(self.counter % self.fireRate == 0): + self.shoot() + self.counter += 1 width, height = self.gameDisplay.get_size() if(self.straight == True): if(self.FacingRight): @@ -256,67 +262,105 @@ def update(self): self.direction = 3 * math.pi / 4 self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the speed to a small change in space self.y = self.y + (self.speed * math.sin(self.direction)) - if(self.x >= width): # if the UFO goes out of the screen, destroy it + if(self.x >= width and self.FacingRight): # if the UFO goes out of the screen, destroy it self.destroyed = True - elif(self.x <= 0 - self.w): + elif(self.x <= 0 - self.w and not self.FacingRight): self.destroyed = True if(self.y >= height): # If the UFOs coordinate goes outside of the window, set that coordinate to the other side of the map self.y = 0 - self.h # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) elif(self.y <= 0 - self.h): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) self.y = height + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + #pygame.draw.rect(self.gameDisplay,(0,0,255),self.rect) # display's the asteroid's hit box in red (for testing) self.gameDisplay.blit(self.image,(self.x,self.y)) def destroy(self): self.destroyed = True -def BigUFO(UFO): - def __init__(self,y,FacingRight,gameDisplay): - super().__init__(y,FacingRight,gameDisplay) +class BigUFO(UFO): + def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): + super().__init__(y,FacingRight,gameDisplay,listOfProjectiles) self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) self.w,self.h = self.image.get_size() - def shoot(self,listOfProjectiles): - listOfProjectiles.addProjectile(self.x,self.y,random.uniform(0,2*math.pi)) + self.shrinkage = 30 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + self.fireRate = 120 + def shoot(self): + if(not self.destroyed): + self.listOfProjectiles.addProjectile(self.x + self.w / 2,self.y + self.h / 2,random.uniform(0,2*math.pi),"UFO") +class CollectionOfUFOs(): + def __init__(self,gameDisplay,listOfProjectiles): + self.listOfUFOs = [] #initializes the projectiles + self.listOfRects = [] # initializes their hitboxes + self.gameDisplay = gameDisplay + self.listOfProjectiles = listOfProjectiles + def spawnBigUFO(self): + width, height = self.gameDisplay.get_size() + sampleUFO = BigUFO(0,True,self.gameDisplay,self.listOfProjectiles) + y = random.randint(-sampleUFO.h // 2,height - sampleUFO.h // 2) + facingRight = bool(random.getrandbits(1)) + self.listOfUFOs.append(BigUFO(y,facingRight,self.gameDisplay,self.listOfProjectiles)) + def update(self): + listOfRects = [] + ListToDelete = [] # initializes the indices of what to delete + for i in range(len(self.listOfUFOs)): + if(self.listOfUFOs[i].destroyed): + ListToDelete.append(i) # adding the index of destroyed particles to delete + else: + self.listOfUFOs[i].update() + listOfRects.append(self.listOfUFOs[i].rect) + for j in reversed(ListToDelete): + del self.listOfUFOs[j] + self.listOfRects = listOfRects class listOfObjects(): - def __init__(self,asteroids,projectiles): - self.Asteroids = asteroids - self.Projectiles = projectiles # contains the CollectionOfAsteroids and CollectionOfProjectiles objects + def __init__(self,gameDisplay): + self.gameDisplay = gameDisplay + self.Asteroids = CollectionOfAsteroids(gameDisplay) + self.Projectiles = CollectionOfProjectiles(gameDisplay) # contains the CollectionOfAsteroids and CollectionOfProjectiles objects + self.UFOs = CollectionOfUFOs(gameDisplay,self.Projectiles) def update(self): - self.Projectiles.update() self.Asteroids.update() - print(len(self.Asteroids.listOfAsteroids),len(self.Asteroids.listOfRects)) - for i in self.Projectiles.listOfProjectiles: # runs throught each projectile - collisions = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile - if (collisions != -1): # if there is a collision - self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisions].destroy() #destroy both the asteroid and the projectile. + self.UFOs.update() + self.Projectiles.update() + for i in self.Projectiles.listOfProjectiles: # runs through each projectile + collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile + if (collisionsAster != -1): # if there is a collision + self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. + i.destroy() + collisionsUFO = i.rect.collidelist(self.UFOs.listOfRects) + if (collisionsUFO != -1 and i.alliance != "UFO"): # if there is a collision + self.UFOs.listOfUFOs[collisionsUFO].destroy() #destroy both the asteroid and the projectile. + i.destroy() + for i in self.UFOs.listOfUFOs: + collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile + if (collisionsAster != -1): # if there is a collision + self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. i.destroy() - pygame.init() gameDisplay = pygame.display.set_mode((800,600)) clock = pygame.time.Clock() numberOfAsteroids = 4 -# CollAster = CollectionOfAsteroids(gameDisplay,1) -# CollAster.spawnAsteroids(numberOfAsteroids) # initiating a list of asteroids to keep track of -# proj = CollectionOfProjectiles(gameDisplay) -# proj.addProjectile(400,300,math.pi / 4) Black = (0,0,0) # black screen is the background gameDisplay.fill(Black) -# AllThings = listOfObjects(CollAster,proj) -# AllThings.update() # testing the many asteroids spawn in the right spot +AllThings = listOfObjects(gameDisplay) +AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) +AllThings.UFOs.spawnBigUFO() +AllThings.update() # testing the many asteroids spawn in the right spot pygame.display.update() running = True # for the exit of the game randomCounter = 0 -UFO = UFO(300,True,gameDisplay) while running: - # randomCounter += 1 - # if(randomCounter % 5 == 0): - # AllThings.Projectiles.addProjectile(400,300,random.uniform(0,2*math.pi)) + randomCounter += 1 + randomInt = random.randint(1,1000) + if(randomInt == 1 and len(AllThings.UFOs.listOfUFOs) == 0): + AllThings.UFOs.spawnBigUFO() + if(randomCounter % 30 == 0): + AllThings.Projectiles.addProjectile(400,300,random.uniform(0,2*math.pi),"Ship") gameDisplay.fill(Black) - # AllThings.update()# update each asteroid - #proj.update() - UFO.update() + AllThings.update()# update each asteroid pygame.display.update() - # if(len(AllThings.Asteroids.listOfAsteroids) == 0): - # numberOfAsteroids += 1 - # AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) + if(len(AllThings.Asteroids.listOfAsteroids) == 0 and len(AllThings.UFOs.listOfUFOs) == 0): + numberOfAsteroids += 1 + AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: From 1657a219a783b48eacfb765a9acc5376107fd712 Mon Sep 17 00:00:00 2001 From: Corey Date: Wed, 14 Mar 2018 10:37:13 -0400 Subject: [PATCH 20/45] Fix movment for ship -Ship movement works -Fixed rotation function -Modified how the ship blips on the screen -Cleared some extraneous code --- classes.py | 46 ++++++++++++++-------------------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/classes.py b/classes.py index c40a194f..8f0cd7d0 100644 --- a/classes.py +++ b/classes.py @@ -23,28 +23,16 @@ def update(self,score): self.gD.blit(box,(0,0)) - def rot_center(image, angle): - """rotate an image while keeping its center and size - Found online. Very helpful - print(type(image)) - """ - orig_rect = image.get_rect() - rot_image = pygame.transform.rotate(image, angle) - rot_rect = orig_rect.copy() - rot_rect.center = rot_image.get_rect().center - rot_image = rot_image.subsurface(rot_rect).copy() - return rot_image -# def rot_center(image, angle): -# """rotate a Surface, maintaining position.""" -# #DOES NOT WORK -# -# loc = image.get_rect().center #rot_image is not defined -# rot_sprite = pygame.transform.rotate(image, angle) -# # rot_sprite.get_rect().center = loc -# rotRect = rot_sprite.get_rect() -# rotRect.center = loc -# return rot_sprite,rotRect + """rotate a Surface, maintaining position.""" + #DOES NOT WORK + + loc = image.get_rect().center #rot_image is not defined + rot_sprite = pygame.transform.rotate(image, angle) + # rot_sprite.get_rect().center = loc + rotRect = rot_sprite.get_rect() + rotRect.center = loc + return rot_sprite,rotRect class Ship(): """Ship class! @@ -57,9 +45,7 @@ class Ship(): oImage (img) original nImage (img) new drift (boolean) - forward (boolean) - ro (boolean) - rdir (1 or -1) + rect (pygame surface) """ x_speed = 0 @@ -88,7 +74,7 @@ def move(self): def rotate(self,posNeg): """Rotates ship""" - self.nImage = rot_center(self.oImage,posNeg*3+(270-self.angle)) + self.nImage,self.rect = rot_center(self.oImage,posNeg*3+(270-self.angle)) self.angle -= posNeg*3 def update(self): @@ -104,7 +90,6 @@ def update(self): self.x_speed = 0 self.y_speed = 0 if speed > 10: - # self.drift = False self.x_speed = cos(radians(self.angle))*10 self.y_speed = sin(radians(self.angle))*10 if self.drift: @@ -112,11 +97,6 @@ def update(self): self.x_speed *= .98 self.y_speed *= .98 - # if self.forward: - # self.move() - # if self.ro: - # self.rotate() - self.y += self.y_speed self.x += self.x_speed @@ -129,4 +109,6 @@ def update(self): elif(self.y <= 0 - self.h): self.y = height - self.gD.blit(self.nImage,(self.x,self.y)) + self.rect.center = (self.x,self.y) + + self.gD.blit(self.nImage,self.rect) From 8817e88bb9d99fcb16a4ae8327e53017014788fe Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 14 Mar 2018 10:47:27 -0400 Subject: [PATCH 21/45] adding asteroid, projectile, and UFO to classes.py --- Asteroid.py | 4 +- classes.py | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 332 insertions(+), 2 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index f1c46ffe..3adb14c0 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -220,7 +220,7 @@ def update(self): class UFO(): def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.y = y - self.speed = 4 + self.speed = 2 self.destroyed = False self.image = pygame.image.load('UFO.gif').convert() self.image.set_colorkey((0,0,0)) @@ -282,7 +282,7 @@ def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.w,self.h = self.image.get_size() self.shrinkage = 30 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) - self.fireRate = 120 + self.fireRate = 60 def shoot(self): if(not self.destroyed): self.listOfProjectiles.addProjectile(self.x + self.w / 2,self.y + self.h / 2,random.uniform(0,2*math.pi),"UFO") diff --git a/classes.py b/classes.py index 8f0cd7d0..772ad600 100644 --- a/classes.py +++ b/classes.py @@ -112,3 +112,333 @@ def update(self): self.rect.center = (self.x,self.y) self.gD.blit(self.nImage,self.rect) + +class Asteroid(): + """ + Asteroid Class: + x - position + y - position + speed - speed of asteroid + direction - direction of asteroid + image - surface containing picture of asteroid + gameDisplay - the display to put the asteroid on + w, h - the width and height of the surface + """ + def __init__(self,x,y,speed,direction,gameDisplay): + self.x = x + self.y = y + self.speed = speed + self.direction = direction + self.image = pygame.image.load('Asteroid.png').convert() + self.image.set_colorkey((0,0,0)) # Sets the Asteroids Blackness to be transparent + self.w, self.h = self.image.get_size() # Gets the Asteroid's width and height + self.destroyed = False + self.gameDisplay = gameDisplay + def update(self): + """ + updates the position of the asteroid and rectangle + """ + if(not self.destroyed): # once the asteroid is destroyed, it will stop redrawing the asteroid + width, height = self.gameDisplay.get_size() # gets the display's width and length + self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the Asteroid's to a small change in space + self.y = self.y + (self.speed * math.sin(self.direction)) + if(self.x >= width): # If the asteroid's coordinate goes outside of the window, set that coordinate to the other side of the map + self.x = 0 - self.w # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) + elif(self.x <= 0 - self.w): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) + self.x = width + if(self.y >= height): + self.y = 0 - self.h + elif(self.y <= 0 - self.h): + self.y = height + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # The Rect is for the hitbox + self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen + #pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) # display's the asteroid's hit box in red (for testing) + +class LargeAsteroid(Asteroid): + + """ + subclass of the asteroid, for the starting asteroids + shrinkage - number that the rectangle hitbox shrinks by + rect - the hitbox rectangle + """ + def __init__(self,x,y,speed,direction,gameDisplay): + super().__init__(x,y,speed,direction,gameDisplay) + self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) # scales the asteroid to size + self.w,self.h = self.image.get_size() + self.shrinkage = 50 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # lessening the hitbox so the corners don't stick out + def destroy(self): + """ + destroys the asteroid and returns the asteroids that should take it's place. + """ + if(not self.destroyed): + self.destroyed = True + MedAster = [] + for i in range(2): + MedAster.append(MediumAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more medium asteroids in it's place with random directions + return MedAster + return [] +class MediumAsteroid(Asteroid): + """ + subclass of the asteroid, for the second asteroid + shrinkage - number that the rectangle hitbox shrinks by + rect - the hitbox rectangle + """ + def __init__(self,x,y,speed,direction,gameDisplay): + super().__init__(x,y,speed,direction,gameDisplay) + self.image = pygame.transform.scale(self.image,(self.w // 4,self.h // 4)) # half as big as large asteroid + self.w,self.h = self.image.get_size() + self.shrinkage = 25 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + def destroy(self): + """ + destroys the asteroid and returns the asteroids that should take it's place. + """ + if(not self.destroyed): + self.destroyed = True + SmallAster = [] + for i in range(2): + SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more small asteroids in it's place with random directions + return SmallAster + return [] +class SmallAsteroid(Asteroid): + """ + subclass of the asteroid, for the last asteroid + shrinkage - number that the rectangle hitbox shrinks by + rect - the hitbox rectangle + """ + def __init__(self,x,y,speed,direction,gameDisplay): + super().__init__(x,y,speed,direction,gameDisplay) + self.image = pygame.transform.scale(self.image,(self.w // 8,self.h // 8)) # half as big as medium asteroid + self.w,self.h = self.image.get_size() + self.shrinkage = 12 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + def destroy(self): + """ + destroys the asteroid and returns nothing because it is the smallest asteroid + """ + self.destroyed = True + return [] +class CollectionOfAsteroids(): + def __init__(self,gameDisplay): + self.listOfAsteroids = [] + self.gameDisplay = gameDisplay + self.speed = 1 + def spawnAsteroids(self,numberOfAsteroids): + width, height = self.gameDisplay.get_size() + listOfAsteroids = [] # initializes a list of asteroids to update + listOfRects = [] # initializes a list of hitboxes + sampleAsteroid = LargeAsteroid(0,0,0,0,self.gameDisplay) # a sample asteroid to know where to spawn the asteroids in case we change the size later + smallArea = 100 # the area that asteroids are to spawn around the the edge + for i in range(numberOfAsteroids): + side = random.randint(1,4) + if(side == 1): # left side of the screen + x = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.h // 2,height - sampleAsteroid.h // 2) + elif(side == 2): # top side of the screen + x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.w // 2,smallArea - sampleAsteroid.w // 2) + elif(side == 3): # right side of the screen + x = random.randint(width-smallArea - sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(-sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) + elif(side == 4): # bottom of the screen + x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) + y = random.randint(height-smallArea - sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) + direction = random.uniform(0,math.pi * 2) # initiate each asteroid with a random direction + listOfAsteroids.append(LargeAsteroid(x,y,self.speed,direction,self.gameDisplay)) + listOfRects.append(listOfAsteroids[i].rect) + self.listOfAsteroids = listOfAsteroids + self.listOfRects = listOfRects + def update(self): + listOfRects = [] # asteroid + ListToDelete = [] # a list that incluedes the indicies of what to delete + for i in range(len(self.listOfAsteroids)): + if(self.listOfAsteroids[i].destroyed): + ListToDelete.append(i) # if the asteroid is destroyed, remember the number to remove it later + else: + self.listOfAsteroids[i].update() + listOfRects.append(self.listOfAsteroids[i].rect) + for j in reversed(ListToDelete): # reversed so that it doesn't delete one and shift mid for loop. + del self.listOfAsteroids[j] + self.listOfRects = listOfRects + def destroyAll(self): # function for testingasteroid, not for the real game + sizeOfAsteroids = range(len(self.listOfAsteroids)) + for i in sizeOfAsteroids: + newAsteroid = self.listOfAsteroids[i].destroy() + if(newAsteroid != None): + self.listOfAsteroids += newAsteroid # destroying all of the asteroids making them medium + for i in sizeOfAsteroids: + self.listOfAsteroids.pop(0) +class Projectile(): + def __init__(self,x,y,direction,alliance,gameDisplay): + size = 3 + self.x = x + self.y = y + self.w = size + self.h = size + self.speed = 10 + self.direction = direction + self.rect = ((self.x,self.y),(size,size)) + self.image = pygame.Surface((size,size)) + self.image.fill((255,255,255)) + self.gameDisplay = gameDisplay + self.destroyed = False + self.distanceTravelled = 0 # asteroids + self.distanceWanted = 500 # the distance that the projectile travels before it is destroyed + self.alliance = alliance + def update(self): + if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself + width, height = self.gameDisplay.get_size() # gets the display's width and length + self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the speed to a small change in space + self.y = self.y + (self.speed * math.sin(self.direction)) + self.distanceTravelled += self.speed # updates the disnance travelled + if(self.x >= width): # If the projectile's coordinate goes outside of the window, set that coordinate to the other side of the map + self.x = 0 - self.w # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) + elif(self.x <= 0 - self.w): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) + self.x = width + if(self.y >= height): + self.y = 0 - self.h + elif(self.y <= 0 - self.h): + self.y = height + self.rect = pygame.Rect((self.x,self.y),(self.w,self.h)) + self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the pixel on the screen + #pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) # display's the projectile's hit box in green (for testing) + else: + self.destroy() # satisfying to right + def destroy(self): + self.destroyed = True +class CollectionOfProjectiles(): + def __init__(self,gameDisplay): + self.listOfProjectiles = [] #initializes the asteroidprojectiles + self.listOfRects = [] # initializes their hitboxes + self.gameDisplay = gameDisplay + def addProjectile(self,x,y,direction,alliance): + self.listOfProjectiles.append(Projectile(x,y,direction,alliance,self.gameDisplay)) # The spacebar command should call this + # with the x,y and directions of the ship (with an offset bc of the front of the ship and that the origin is top left) + def update(self): + ListToDelete = [] # initializes the indices of what to delete + for i in range(len(self.listOfProjectiles)): + if(self.listOfProjectiles[i].destroyed): + ListToDelete.append(i) # adding the index of destroyed particles to delete + else: + self.listOfProjectiles[i].update() + for j in reversed(ListToDelete): + del self.listOfProjectiles[j] + +class UFO(): + def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): + self.y = y + self.speed = 2 + self.destroyed = False + self.image = pygame.image.load('UFO.gif').convert() + self.image.set_colorkey((0,0,0)) + self.w, self.h = self.image.get_size() + self.straight = bool(random.getrandbits(1)) + self.FacingRight = FacingRight + self.gameDisplay = gameDisplay + width, height = gameDisplay.get_size() + self.counter = 0 + self.listOfProjectiles = listOfProjectiles + if(FacingRight): + self.x = -self.w + else: + self.x = width + def update(self): + if(self.counter % self.fireRate == 0): + self.shoot() + self.counter += 1 + width, height = self.gameDisplay.get_size() + if(self.straight == True): + if(self.FacingRight): + self.direction = 0 + else: + self.direction = math.pi + else: + if(self.FacingRight): + if((self.x + self.w / 2) < width * 1 / 4): + self.direction = 0 + elif(self.x + self.w / 2 < width / 2): + self.direction = math.pi / 4 + else: + self.direction = - math.pi / 4 + else: + if((self.x + self.w / 2) > width * 3 / 4): + self.direction = math.pi + elif(self.x + self.w / 2 > width / 2): + self.direction = 5 * math.pi / 4 + else: + self.direction = 3 * math.pi / 4 + self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the speed to a small change in space + self.y = self.y + (self.speed * math.sin(self.direction)) + if(self.x >= width and self.FacingRight): # if the UFO goes out of the screen, destroy it + self.destroyed = True + elif(self.x <= 0 - self.w and not self.FacingRight): + self.destroyed = True + if(self.y >= height): # If the UFOs coordinate goes outside of the window, set that coordinate to the other side of the map + self.y = 0 - self.h # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) + elif(self.y <= 0 - self.h): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) + self.y = height + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + #pygame.draw.rect(self.gameDisplay,(0,0,255),self.rect) # display's the asteroid's hit box in red (for testing) + self.gameDisplay.blit(self.image,(self.x,self.y)) + def destroy(self): + self.destroyed = True +class BigUFO(UFO): + def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): + super().__init__(y,FacingRight,gameDisplay,listOfProjectiles) + self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) + self.w,self.h = self.image.get_size() + self.shrinkage = 30 + self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + self.fireRate = 60 + def shoot(self): + if(not self.destroyed): + self.listOfProjectiles.addProjectile(self.x + self.w / 2,self.y + self.h / 2,random.uniform(0,2*math.pi),"UFO") +class CollectionOfUFOs(): + def __init__(self,gameDisplay,listOfProjectiles): + self.listOfUFOs = [] #initializes the projectiles + self.listOfRects = [] # initializes their hitboxes + self.gameDisplay = gameDisplay + self.listOfProjectiles = listOfProjectiles + def spawnBigUFO(self): + width, height = self.gameDisplay.get_size() + sampleUFO = BigUFO(0,True,self.gameDisplay,self.listOfProjectiles) + y = random.randint(-sampleUFO.h // 2,height - sampleUFO.h // 2) + facingRight = bool(random.getrandbits(1)) + self.listOfUFOs.append(BigUFO(y,facingRight,self.gameDisplay,self.listOfProjectiles)) + def update(self): + listOfRects = [] + ListToDelete = [] # initializes the indices of what to delete + for i in range(len(self.listOfUFOs)): + if(self.listOfUFOs[i].destroyed): + ListToDelete.append(i) # adding the index of destroyed particles to delete + else: + self.listOfUFOs[i].update() + listOfRects.append(self.listOfUFOs[i].rect) + for j in reversed(ListToDelete): + del self.listOfUFOs[j] + self.listOfRects = listOfRects +class listOfObjects(): + def __init__(self,gameDisplay): + self.gameDisplay = gameDisplay + self.Asteroids = CollectionOfAsteroids(gameDisplay) + self.Projectiles = CollectionOfProjectiles(gameDisplay) # contains the CollectionOfAsteroids and CollectionOfProjectiles objects + self.UFOs = CollectionOfUFOs(gameDisplay,self.Projectiles) + def update(self): + self.Asteroids.update() + self.UFOs.update() + self.Projectiles.update() + for i in self.Projectiles.listOfProjectiles: # runs through each projectile + collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile + if (collisionsAster != -1): # if there is a collision + self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. + i.destroy() + collisionsUFO = i.rect.collidelist(self.UFOs.listOfRects) + if (collisionsUFO != -1 and i.alliance != "UFO"): # if there is a collision + self.UFOs.listOfUFOs[collisionsUFO].destroy() #destroy both the asteroid and the projectile. + i.destroy() + for i in self.UFOs.listOfUFOs: + collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile + if (collisionsAster != -1): # if there is a collision + self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. + i.destroy() From 116c7a9c7cda0b37793a4f18f3a8123ea9b58256 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 14 Mar 2018 10:59:00 -0400 Subject: [PATCH 22/45] adding UFO.gif --- UFO.gif | Bin 0 -> 375 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 UFO.gif diff --git a/UFO.gif b/UFO.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe6c0b874901f1e78cef958d504e0eb60a5c27f9 GIT binary patch literal 375 zcmV--0f_!bNk%w1VU_@70Du4h00030|Nkri0001%0Av6F0{(=LsmtvTqnxzbi?iOm z`wxcVNS5Y_rs~SJ?hD8AOxN~}=lag~{tpZahs2`sh)gP%%%<}RjY_A~YAb-vYPa01 z_0 Date: Wed, 14 Mar 2018 11:08:07 -0400 Subject: [PATCH 23/45] Integrate asteroids and interface -Ship now moves among the asteroids! -scaled ship better -Classes now holds all of the classes -packages up to date in each file --- classes.py | 4 ++++ interface.py | 42 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/classes.py b/classes.py index 772ad600..4e7cb0a8 100644 --- a/classes.py +++ b/classes.py @@ -1,5 +1,9 @@ import pygame from math import cos,sin,sqrt,radians,atan +from pygame.locals import * +import time +import math +import random pygame.init() diff --git a/interface.py b/interface.py index 0cbf1d2b..bf95c9a8 100644 --- a/interface.py +++ b/interface.py @@ -6,36 +6,49 @@ """ import pygame -from math import cos,sin,sqrt,radians,atan +from math import cos,sin,sqrt,radians,atan,pi from classes import * +import time +import random +""" initiate pygame """ pygame.init() -display_width = 1000 -display_height = 800 -imgScale = .2 - +""" initiate screen """ +display_width = 1600 +display_height = 1200 +imgScale = .13 gameDisplay = pygame.display.set_mode((display_width,display_height)) pygame.display.set_caption("Asteroids") - black = (0,0,0) white = (255,255,255) +""" some other important things """ clock = pygame.time.Clock() running = True -shipImg = pygame.image.load('spa1.png') +""" initiate ship object """ +shipImg = pygame.image.load('spa1.png') shipX = (display_width * .5) shipY = (display_height * .5) w,h = shipImg.get_size() shipImg = pygame.transform.scale(shipImg,(int(w*imgScale),int(h*imgScale))) ship = Ship(shipX,shipY,270,shipImg,gameDisplay) +""" initiate asteroids and UFOs """ +numberOfAsteroids = 4 +AllThings = listOfObjects(gameDisplay) +AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) +AllThings.UFOs.spawnBigUFO() +AllThings.update() # testing the many asteroids spawn in the right spot + +""" initiate GUI """ gui = GUI(gameDisplay) while running: + """ listens to events and does stuff """ for event in pygame.event.get(): if event.type == pygame.QUIT: running = False @@ -43,8 +56,8 @@ if event.type == pygame.KEYUP: if event.key == pygame.K_q: running = False + """ player interface """ keys_pressed = pygame.key.get_pressed() - if keys_pressed[pygame.K_UP]: ship.move() else: @@ -54,9 +67,22 @@ if keys_pressed[pygame.K_RIGHT]: ship.rotate(-1) + """ UFO spawning """ + randomInt = random.randint(1,1000) + if(randomInt == 1 and len(AllThings.UFOs.listOfUFOs) == 0): + AllThings.UFOs.spawnBigUFO() + + """ spawns new level """ + if(len(AllThings.Asteroids.listOfAsteroids) == 0 and len(AllThings.UFOs.listOfUFOs) == 0): + numberOfAsteroids += 1 + AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) + + + gameDisplay.fill(black) gui.update(150000) ship.update() + AllThings.update() pygame.display.update() clock.tick(60) From 4db39d4a2cbf4db96eccdf25bdeab64ffc9a3a81 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 14 Mar 2018 11:23:55 -0400 Subject: [PATCH 24/45] added shooting --- Asteroid.py | 26 +++++++++++++++++++++++++- classes.py | 46 ++++++++++++++++++++++------------------------ interface.py | 3 ++- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index 3adb14c0..6b892948 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -112,11 +112,19 @@ def destroy(self): self.destroyed = True return [] class CollectionOfAsteroids(): + """ + A collection of the Asteroids in the game + listOfAsteroids - a list of the asteroids in the game + gameDisplay - the display + """ def __init__(self,gameDisplay): self.listOfAsteroids = [] self.gameDisplay = gameDisplay self.speed = 1 def spawnAsteroids(self,numberOfAsteroids): + """ + spawns a set number of asteroids in the sides of the game + """ width, height = self.gameDisplay.get_size() listOfAsteroids = [] # initializes a list of asteroids to update listOfRects = [] # initializes a list of hitboxes @@ -142,6 +150,9 @@ def spawnAsteroids(self,numberOfAsteroids): self.listOfAsteroids = listOfAsteroids self.listOfRects = listOfRects def update(self): + """ + updates all the asteroids, deleting them from the list if they are destroyed. + """ listOfRects = [] # asteroid ListToDelete = [] # a list that incluedes the indicies of what to delete for i in range(len(self.listOfAsteroids)): @@ -162,6 +173,18 @@ def destroyAll(self): # function for testingasteroid, not for the real game for i in sizeOfAsteroids: self.listOfAsteroids.pop(0) class Projectile(): + """ + projectiles that fire and destroy asteroids, ufos and players. + x - position x + y - position y + w, h - size of the projectiles + speed - speed of the projectile + direction- direction given to the projectiles + rect - the hitbox of the projectile + gameDisplay - the display + destroyed - senses whether the projectile is destroyed or not + distanceTravelled - detects how far the projectile has travelled + """ def __init__(self,x,y,direction,alliance,gameDisplay): size = 3 self.x = x @@ -176,7 +199,7 @@ def __init__(self,x,y,direction,alliance,gameDisplay): self.gameDisplay = gameDisplay self.destroyed = False self.distanceTravelled = 0 # asteroids - self.distanceWanted = 500 # the distance that the projectile travels before it is destroyed + self.distanceWanted = # the distance that the projectile travels before it is destroyed self.alliance = alliance def update(self): if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself @@ -335,6 +358,7 @@ def update(self): self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. i.destroy() + pygame.init() gameDisplay = pygame.display.set_mode((800,600)) clock = pygame.time.Clock() diff --git a/classes.py b/classes.py index 4e7cb0a8..9f103fce 100644 --- a/classes.py +++ b/classes.py @@ -1,10 +1,6 @@ import pygame -from math import cos,sin,sqrt,radians,atan -from pygame.locals import * -import time -import math +from math import cos,sin,sqrt,radians,atan,pi import random - pygame.init() class GUI(): @@ -116,7 +112,11 @@ def update(self): self.rect.center = (self.x,self.y) self.gD.blit(self.nImage,self.rect) - + def shoot(self,AllThings): + x,y = self.rect.center + x = x + int(5 * cos(self.angle)) + y = y + int(5 * sin(self.angle)) + AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") class Asteroid(): """ Asteroid Class: @@ -144,8 +144,8 @@ def update(self): """ if(not self.destroyed): # once the asteroid is destroyed, it will stop redrawing the asteroid width, height = self.gameDisplay.get_size() # gets the display's width and length - self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the Asteroid's to a small change in space - self.y = self.y + (self.speed * math.sin(self.direction)) + self.x = self.x + (self.speed * cos(self.direction)) # Sets the Asteroid's to a small change in space + self.y = self.y + (self.speed * sin(self.direction)) if(self.x >= width): # If the asteroid's coordinate goes outside of the window, set that coordinate to the other side of the map self.x = 0 - self.w # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) elif(self.x <= 0 - self.w): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) @@ -157,7 +157,6 @@ def update(self): self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # The Rect is for the hitbox self.gameDisplay.blit(self.image,(self.x,self.y)) # draws the asteroid on the screen #pygame.draw.rect(self.gameDisplay,(0,255,0),self.rect) # display's the asteroid's hit box in red (for testing) - class LargeAsteroid(Asteroid): """ @@ -179,7 +178,7 @@ def destroy(self): self.destroyed = True MedAster = [] for i in range(2): - MedAster.append(MediumAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more medium asteroids in it's place with random directions + MedAster.append(MediumAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*pi),self.gameDisplay)) #makes two more medium asteroids in it's place with random directions return MedAster return [] class MediumAsteroid(Asteroid): @@ -202,7 +201,7 @@ def destroy(self): self.destroyed = True SmallAster = [] for i in range(2): - SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*math.pi),self.gameDisplay)) #makes two more small asteroids in it's place with random directions + SmallAster.append(SmallAsteroid(self.x,self.y,self.speed*1.5,random.uniform(0,2*pi),self.gameDisplay)) #makes two more small asteroids in it's place with random directions return SmallAster return [] class SmallAsteroid(Asteroid): @@ -248,7 +247,7 @@ def spawnAsteroids(self,numberOfAsteroids): elif(side == 4): # bottom of the screen x = random.randint(-sampleAsteroid.w // 2,width - sampleAsteroid.w // 2) y = random.randint(height-smallArea - sampleAsteroid.w // 2,height - sampleAsteroid.w // 2) - direction = random.uniform(0,math.pi * 2) # initiate each asteroid with a random direction + direction = random.uniform(0,pi * 2) # initiate each asteroid with a random direction listOfAsteroids.append(LargeAsteroid(x,y,self.speed,direction,self.gameDisplay)) listOfRects.append(listOfAsteroids[i].rect) self.listOfAsteroids = listOfAsteroids @@ -293,8 +292,8 @@ def __init__(self,x,y,direction,alliance,gameDisplay): def update(self): if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself width, height = self.gameDisplay.get_size() # gets the display's width and length - self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the speed to a small change in space - self.y = self.y + (self.speed * math.sin(self.direction)) + self.x = self.x + (self.speed * cos(self.direction)) # Sets the speed to a small change in space + self.y = self.y + (self.speed * sin(self.direction)) self.distanceTravelled += self.speed # updates the disnance travelled if(self.x >= width): # If the projectile's coordinate goes outside of the window, set that coordinate to the other side of the map self.x = 0 - self.w # adding the width of the image to make sure that the image doesn't appear suddenly (the image's position is the top right of the image) @@ -328,7 +327,6 @@ def update(self): self.listOfProjectiles[i].update() for j in reversed(ListToDelete): del self.listOfProjectiles[j] - class UFO(): def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.y = y @@ -356,24 +354,24 @@ def update(self): if(self.FacingRight): self.direction = 0 else: - self.direction = math.pi + self.direction = pi else: if(self.FacingRight): if((self.x + self.w / 2) < width * 1 / 4): self.direction = 0 elif(self.x + self.w / 2 < width / 2): - self.direction = math.pi / 4 + self.direction = pi / 4 else: - self.direction = - math.pi / 4 + self.direction = - pi / 4 else: if((self.x + self.w / 2) > width * 3 / 4): - self.direction = math.pi + self.direction = pi elif(self.x + self.w / 2 > width / 2): - self.direction = 5 * math.pi / 4 + self.direction = 5 * pi / 4 else: - self.direction = 3 * math.pi / 4 - self.x = self.x + (self.speed * math.cos(self.direction)) # Sets the speed to a small change in space - self.y = self.y + (self.speed * math.sin(self.direction)) + self.direction = 3 * pi / 4 + self.x = self.x + (self.speed * cos(self.direction)) # Sets the speed to a small change in space + self.y = self.y + (self.speed * sin(self.direction)) if(self.x >= width and self.FacingRight): # if the UFO goes out of the screen, destroy it self.destroyed = True elif(self.x <= 0 - self.w and not self.FacingRight): @@ -397,7 +395,7 @@ def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.fireRate = 60 def shoot(self): if(not self.destroyed): - self.listOfProjectiles.addProjectile(self.x + self.w / 2,self.y + self.h / 2,random.uniform(0,2*math.pi),"UFO") + self.listOfProjectiles.addProjectile(self.x + self.w / 2,self.y + self.h / 2,random.uniform(0,2*pi),"UFO") class CollectionOfUFOs(): def __init__(self,gameDisplay,listOfProjectiles): self.listOfUFOs = [] #initializes the projectiles diff --git a/interface.py b/interface.py index bf95c9a8..b474e8b9 100644 --- a/interface.py +++ b/interface.py @@ -66,7 +66,8 @@ ship.rotate(1) if keys_pressed[pygame.K_RIGHT]: ship.rotate(-1) - + if keys_pressed[pygame.K_SPACE]: + ship.shoot(AllThings) """ UFO spawning """ randomInt = random.randint(1,1000) if(randomInt == 1 and len(AllThings.UFOs.listOfUFOs) == 0): From 24ba29b76aecfb0376fb04ce638b39672ec27d9b Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 14 Mar 2018 11:38:26 -0400 Subject: [PATCH 25/45] added shooting at a certain rate of fire --- classes.py | 5 ++--- interface.py | 14 +++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/classes.py b/classes.py index 9f103fce..086231ea 100644 --- a/classes.py +++ b/classes.py @@ -113,9 +113,8 @@ def update(self): self.gD.blit(self.nImage,self.rect) def shoot(self,AllThings): - x,y = self.rect.center - x = x + int(5 * cos(self.angle)) - y = y + int(5 * sin(self.angle)) + x = self.x + int(5 * cos(self.angle)) + y = self.y + int(5 * sin(self.angle)) AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") class Asteroid(): """ diff --git a/interface.py b/interface.py index b474e8b9..35cb1945 100644 --- a/interface.py +++ b/interface.py @@ -46,6 +46,9 @@ """ initiate GUI """ gui = GUI(gameDisplay) +""" initialize the ship to be able to shoot""" +canShoot = True + while running: """ listens to events and does stuff """ @@ -66,8 +69,17 @@ ship.rotate(1) if keys_pressed[pygame.K_RIGHT]: ship.rotate(-1) + if(canShoot): + counter = 0 + else: + counter += 1 + if(counter >= 20): + canShoot = True if keys_pressed[pygame.K_SPACE]: - ship.shoot(AllThings) + if(canShoot): + ship.shoot(AllThings) + canShoot = False + counter = 0 """ UFO spawning """ randomInt = random.randint(1,1000) if(randomInt == 1 and len(AllThings.UFOs.listOfUFOs) == 0): From 1c9ce85d706b2f1ab302c5ec572ba7800cbc1429 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 14 Mar 2018 11:53:00 -0400 Subject: [PATCH 26/45] added destroy function and code to call it in Allthings --- classes.py | 21 +++++++++++++++++++-- interface.py | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/classes.py b/classes.py index 086231ea..a0a9a175 100644 --- a/classes.py +++ b/classes.py @@ -112,10 +112,13 @@ def update(self): self.rect.center = (self.x,self.y) self.gD.blit(self.nImage,self.rect) + pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing) def shoot(self,AllThings): x = self.x + int(5 * cos(self.angle)) y = self.y + int(5 * sin(self.angle)) AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") + def destroy(self): + print("destroyed") class Asteroid(): """ Asteroid Class: @@ -284,9 +287,10 @@ def __init__(self,x,y,direction,alliance,gameDisplay): self.image = pygame.Surface((size,size)) self.image.fill((255,255,255)) self.gameDisplay = gameDisplay + width,height = self.gameDisplay.get_size() self.destroyed = False self.distanceTravelled = 0 # asteroids - self.distanceWanted = 500 # the distance that the projectile travels before it is destroyed + self.distanceWanted = 5/8 * height # the distance that the projectile travels before it is destroyed self.alliance = alliance def update(self): if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself @@ -420,15 +424,28 @@ def update(self): del self.listOfUFOs[j] self.listOfRects = listOfRects class listOfObjects(): - def __init__(self,gameDisplay): + def __init__(self,gameDisplay, ship): self.gameDisplay = gameDisplay self.Asteroids = CollectionOfAsteroids(gameDisplay) self.Projectiles = CollectionOfProjectiles(gameDisplay) # contains the CollectionOfAsteroids and CollectionOfProjectiles objects self.UFOs = CollectionOfUFOs(gameDisplay,self.Projectiles) + self.ship = ship def update(self): self.Asteroids.update() self.UFOs.update() self.Projectiles.update() + collisionsAster = self.ship.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile + if (collisionsAster != -1): # if there is a collision + self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. + self.ship.destroy() + collisionsUFO = self.ship.rect.collidelist(self.UFOs.listOfRects) + if (collisionsUFO != -1): # if there is a collision + #self.UFOs.listOfUFOs[collisionsUFO].destroy() #destroy both the asteroid and the projectile. + self.ship.destroy() + collisionsProj = self.ship.rect.collidelist(self.Projectiles.listOfRects) + if (collisionsProj != -1): + self.Projectiles.listOfProjectiles[collisionsProj].destroy() + self.ship.destroy() for i in self.Projectiles.listOfProjectiles: # runs through each projectile collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile if (collisionsAster != -1): # if there is a collision diff --git a/interface.py b/interface.py index 35cb1945..f5b3fe62 100644 --- a/interface.py +++ b/interface.py @@ -38,7 +38,7 @@ """ initiate asteroids and UFOs """ numberOfAsteroids = 4 -AllThings = listOfObjects(gameDisplay) +AllThings = listOfObjects(gameDisplay,ship) AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) AllThings.UFOs.spawnBigUFO() AllThings.update() # testing the many asteroids spawn in the right spot From b7ebeb8dbfb5d7ab352c2f65c7d907cc02593f43 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 14 Mar 2018 11:55:43 -0400 Subject: [PATCH 27/45] added some comments to Asteroids --- Asteroid.py | 3 ++- classes.py | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index 6b892948..e8978c77 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -199,7 +199,8 @@ def __init__(self,x,y,direction,alliance,gameDisplay): self.gameDisplay = gameDisplay self.destroyed = False self.distanceTravelled = 0 # asteroids - self.distanceWanted = # the distance that the projectile travels before it is destroyed + width, height = self.gameDisplay.get_size() + self.distanceWanted = 5/8 * # the distance that the projectile travels before it is destroyed self.alliance = alliance def update(self): if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself diff --git a/classes.py b/classes.py index a0a9a175..b9705421 100644 --- a/classes.py +++ b/classes.py @@ -118,7 +118,7 @@ def shoot(self,AllThings): y = self.y + int(5 * sin(self.angle)) AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") def destroy(self): - print("destroyed") + print("destroyed") # right now just a test, need to put something else here class Asteroid(): """ Asteroid Class: @@ -290,7 +290,10 @@ def __init__(self,x,y,direction,alliance,gameDisplay): width,height = self.gameDisplay.get_size() self.destroyed = False self.distanceTravelled = 0 # asteroids - self.distanceWanted = 5/8 * height # the distance that the projectile travels before it is destroyed + if(alliance == "Ship"): + self.distanceWanted = 5/8 * height # the distance that the projectile travels before it is destroyed + else: + self.distanceWanted = 3/8 * height self.alliance = alliance def update(self): if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself From 048aa9fb0551400fdd8305dbdaafe257bda1df78 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Wed, 14 Mar 2018 12:13:07 -0400 Subject: [PATCH 28/45] simple bug fix with the projectile distance --- classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes.py b/classes.py index b9705421..48fb9539 100644 --- a/classes.py +++ b/classes.py @@ -112,7 +112,7 @@ def update(self): self.rect.center = (self.x,self.y) self.gD.blit(self.nImage,self.rect) - pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing) + #pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing) def shoot(self,AllThings): x = self.x + int(5 * cos(self.angle)) y = self.y + int(5 * sin(self.angle)) From c4e2efa4fae03e2af06e757baca331e95b8343a1 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Thu, 15 Mar 2018 18:38:23 -0400 Subject: [PATCH 29/45] adding in lives --- classes.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/classes.py b/classes.py index 48fb9539..d18a366c 100644 --- a/classes.py +++ b/classes.py @@ -63,6 +63,8 @@ def __init__(self,x,y,angle,img,gD): self.w,self.h = img.get_size() self.gD = gD self.rect = img.get_rect() + self.score = 0 + self.lives = 3 def move(self): """FORWARD!!! Moves the ship forward in the direction it's heading (its angle) @@ -118,7 +120,8 @@ def shoot(self,AllThings): y = self.y + int(5 * sin(self.angle)) AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") def destroy(self): - print("destroyed") # right now just a test, need to put something else here + self.lives = self.lives - 1 # right now just a test, need to put something else here + print(self.lives) class Asteroid(): """ Asteroid Class: @@ -172,6 +175,7 @@ def __init__(self,x,y,speed,direction,gameDisplay): self.w,self.h = self.image.get_size() self.shrinkage = 50 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) # lessening the hitbox so the corners don't stick out + self.type = "Large" def destroy(self): """ destroys the asteroid and returns the asteroids that should take it's place. @@ -195,6 +199,7 @@ def __init__(self,x,y,speed,direction,gameDisplay): self.w,self.h = self.image.get_size() self.shrinkage = 25 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + self.type = "Medium" def destroy(self): """ destroys the asteroid and returns the asteroids that should take it's place. @@ -218,6 +223,7 @@ def __init__(self,x,y,speed,direction,gameDisplay): self.w,self.h = self.image.get_size() self.shrinkage = 12 self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) + self.type = "Small" def destroy(self): """ destroys the asteroid and returns nothing because it is the smallest asteroid @@ -452,12 +458,20 @@ def update(self): for i in self.Projectiles.listOfProjectiles: # runs through each projectile collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile if (collisionsAster != -1): # if there is a collision + if(i.alliance == "Ship"): + if(self.Asteroids.listOfAsteroids[collisionsAster].type == "Large"): + self.ship.score += 20 + elif(self.Asteroids.listOfAsteroids[collisionsAster].type == "Medium"): + self.ship.score += 50 + elif(self.Asteroids.listOfAsteroids[collisionsAster].type == "Small"): + self.ship.score += 100 self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. i.destroy() collisionsUFO = i.rect.collidelist(self.UFOs.listOfRects) if (collisionsUFO != -1 and i.alliance != "UFO"): # if there is a collision self.UFOs.listOfUFOs[collisionsUFO].destroy() #destroy both the asteroid and the projectile. i.destroy() + self.ship.score += 500 for i in self.UFOs.listOfUFOs: collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile if (collisionsAster != -1): # if there is a collision From 18f60159da65f669e211cbe8d4bd66a3f58914a6 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Thu, 15 Mar 2018 18:45:34 -0400 Subject: [PATCH 30/45] added ship moving back to spawn location. still needs to be invulnerable or waint until asteroids are clear --- classes.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/classes.py b/classes.py index d18a366c..7b561b0f 100644 --- a/classes.py +++ b/classes.py @@ -55,7 +55,10 @@ def __init__(self,x,y,angle,img,gD): """ Initliazes with where the ship is facing as the angle """ + self.startingAngle = angle self.angle = angle + self.startingX = x + self.startingY = y self.x = x self.y = y self.oImage = img @@ -112,7 +115,6 @@ def update(self): self.y = height self.rect.center = (self.x,self.y) - self.gD.blit(self.nImage,self.rect) #pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing) def shoot(self,AllThings): @@ -121,7 +123,11 @@ def shoot(self,AllThings): AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") def destroy(self): self.lives = self.lives - 1 # right now just a test, need to put something else here - print(self.lives) + self.x = self.startingX + self.y = self.startingY + self.angle = self.startingAngle + self.x_speed = 0 + self.y_speed = 0 class Asteroid(): """ Asteroid Class: From 98872776860b3da54100683e06bfc60074b538ea Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 15 Mar 2018 18:53:14 -0400 Subject: [PATCH 31/45] Add score and lives to GUI -Fixed GUI -Passes ship into update() instead -Should work with integration --- classes.py | 14 +++++++++----- interface.py | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/classes.py b/classes.py index 7b561b0f..b6393b42 100644 --- a/classes.py +++ b/classes.py @@ -12,15 +12,19 @@ class GUI(): def __init__(self,gD): self.gD = gD - def update(self,score): + def update(self,ship): box = pygame.surface.Surface((self.bx, self.by)) - # txt_surf = self.font.render("score", True, self.WHITE) # headline - # txt_rect = txt_surf.get_rect(center=(self.bx//2, 30)) - # box.blit(txt_surf, txt_rect) - txt_surf = self.font.render(str(score), True, self.WHITE) # bottom line + txt_surf = self.font.render(str(ship.score), True, self.WHITE) # bottom line txt_rect = txt_surf.get_rect(center=(self.bx//2, 40)) box.blit(txt_surf, txt_rect) + w,h = ship.oImage.get_size() + txt_surf = pygame.transform.scale(ship.oImage,(int(w*.5),int(h*.5))) + for x in range(ship.lives): + spacing = x*45 + txt_rect = txt_surf.get_rect(center=(self.bx//2-45+spacing, 90)) + box.blit(txt_surf, txt_rect) self.gD.blit(box,(0,0)) + # self.bx//2, 70) def rot_center(image, angle): diff --git a/interface.py b/interface.py index f5b3fe62..ce1040e2 100644 --- a/interface.py +++ b/interface.py @@ -93,7 +93,7 @@ gameDisplay.fill(black) - gui.update(150000) + gui.update(ship) ship.update() AllThings.update() From ffbbcd18f40c2bac539a7628bb46b177e390cfaf Mon Sep 17 00:00:00 2001 From: nathanestill Date: Thu, 15 Mar 2018 18:55:06 -0400 Subject: [PATCH 32/45] added invulnerability frames --- classes.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/classes.py b/classes.py index b6393b42..ac93f6a4 100644 --- a/classes.py +++ b/classes.py @@ -72,6 +72,7 @@ def __init__(self,x,y,angle,img,gD): self.rect = img.get_rect() self.score = 0 self.lives = 3 + self.destroyed = False def move(self): """FORWARD!!! Moves the ship forward in the direction it's heading (its angle) @@ -91,6 +92,10 @@ def update(self): Does magic and makes the ship work. Updates position """ + if(self.destroyed): + self.counter += 1 + if(self.counter > 120): + self.destroyed = False width,height = self.gD.get_size() speed = sqrt(self.x_speed**2+self.y_speed**2) # print(speed) @@ -126,12 +131,15 @@ def shoot(self,AllThings): y = self.y + int(5 * sin(self.angle)) AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") def destroy(self): - self.lives = self.lives - 1 # right now just a test, need to put something else here - self.x = self.startingX - self.y = self.startingY - self.angle = self.startingAngle - self.x_speed = 0 - self.y_speed = 0 + if(self.destroyed == False): + self.lives = self.lives - 1 # right now just a test, need to put something else here + self.x = self.startingX + self.y = self.startingY + self.angle = self.startingAngle + self.x_speed = 0 + self.y_speed = 0 + self.destroyed = True + self.counter = 0 class Asteroid(): """ Asteroid Class: @@ -484,6 +492,6 @@ def update(self): self.ship.score += 500 for i in self.UFOs.listOfUFOs: collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile - if (collisionsAster != -1): # if there is a collision + if (collisionsAster != -1 and self.destroyed == False): # if there is a collision self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. i.destroy() From da72f74d59a9890ce275b0db5bd740cbdde12211 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Thu, 15 Mar 2018 18:55:35 -0400 Subject: [PATCH 33/45] added invulnerability frames --- classes.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/classes.py b/classes.py index ac93f6a4..2856a6c6 100644 --- a/classes.py +++ b/classes.py @@ -72,7 +72,6 @@ def __init__(self,x,y,angle,img,gD): self.rect = img.get_rect() self.score = 0 self.lives = 3 - self.destroyed = False def move(self): """FORWARD!!! Moves the ship forward in the direction it's heading (its angle) @@ -92,10 +91,6 @@ def update(self): Does magic and makes the ship work. Updates position """ - if(self.destroyed): - self.counter += 1 - if(self.counter > 120): - self.destroyed = False width,height = self.gD.get_size() speed = sqrt(self.x_speed**2+self.y_speed**2) # print(speed) @@ -131,15 +126,12 @@ def shoot(self,AllThings): y = self.y + int(5 * sin(self.angle)) AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") def destroy(self): - if(self.destroyed == False): - self.lives = self.lives - 1 # right now just a test, need to put something else here - self.x = self.startingX - self.y = self.startingY - self.angle = self.startingAngle - self.x_speed = 0 - self.y_speed = 0 - self.destroyed = True - self.counter = 0 + self.lives = self.lives - 1 # right now just a test, need to put something else here + self.x = self.startingX + self.y = self.startingY + self.angle = self.startingAngle + self.x_speed = 0 + self.y_speed = 0 class Asteroid(): """ Asteroid Class: @@ -462,7 +454,7 @@ def update(self): self.UFOs.update() self.Projectiles.update() collisionsAster = self.ship.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile - if (collisionsAster != -1): # if there is a collision + if (collisionsAster != -1 and self.ship.destroyed == False): # if there is a collision self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. self.ship.destroy() collisionsUFO = self.ship.rect.collidelist(self.UFOs.listOfRects) @@ -492,6 +484,6 @@ def update(self): self.ship.score += 500 for i in self.UFOs.listOfUFOs: collisionsAster = i.rect.collidelist(self.Asteroids.listOfRects) # detects if any of the asteroids are in contact with the projectile - if (collisionsAster != -1 and self.destroyed == False): # if there is a collision + if (collisionsAster != -1): # if there is a collision self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. i.destroy() From c5e1c4763fb93e42ed3559560c888591c7bbe91c Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 15 Mar 2018 19:23:46 -0400 Subject: [PATCH 34/45] Start markdown file for reflection -Added outline for each section -Added requirements at the bottom --- ProjectReflection.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 ProjectReflection.md diff --git a/ProjectReflection.md b/ProjectReflection.md new file mode 100644 index 00000000..6bffd418 --- /dev/null +++ b/ProjectReflection.md @@ -0,0 +1,36 @@ +# Project Reflection +### Authors: Corey Cochran-Lepiz, Nathan Estill + +## Project Overview [max 100 words] + +We created a Pygame version of the classic arcade game, Asteroids. + +## Results [~2-3 paragraphs + figures/examples] + +We ended up with a game that does a good job resembling the original game. +(INSERT FIGURE HERE) + +## Implementation [~2-3 paragraphs + UML diagram] + +## Reflection [~2 paragraphs] + + +Please prepare a short document (~1 page not including figures) with the following sections: + +Project Overview [Maximum 100 words] + +Write a short abstract describing your project. + +Results [~2-3 paragraphs + figures/examples] + +Present what you accomplished. This will be different for each project, but screenshots are likely to be helpful. + +Implementation [~2-3 paragraphs + UML diagram] + +Describe your implementation at a system architecture level. Include a UML class diagram, and talk about the major components, algorithms, data structures and how they fit together. You should also discuss at least one design decision where you had to choose between multiple alternatives, and explain why you made the choice you did. + +Reflection [~2 paragraphs] + +From a process point of view, what went well? What could you improve? Other possible reflection topics: Was your project appropriately scoped? Did you have a good plan for unit testing? How will you use what you learned going forward? What do you wish you knew before you started that would have helped you succeed? + +Also discuss your team process in your reflection. How did you plan to divide the work (e.g. split by class, always pair program together, etc.) and how did it actually happen? Were there any issues that arose while working together, and how did you address them? What would you do differently next time? From af75542346563a59503ff6da706c7110d80b6315 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Thu, 15 Mar 2018 19:26:52 -0400 Subject: [PATCH 35/45] partially added hitbox shrinking --- classes.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/classes.py b/classes.py index 2856a6c6..b22e7c06 100644 --- a/classes.py +++ b/classes.py @@ -69,9 +69,12 @@ def __init__(self,x,y,angle,img,gD): self.nImage = img self.w,self.h = img.get_size() self.gD = gD - self.rect = img.get_rect() + self.rect = img.get_rect().inflate(-30,-30) + self.rect.center = (self.x,self.y) self.score = 0 self.lives = 3 + self.destroyed = False + self.extraLives = 1 def move(self): """FORWARD!!! Moves the ship forward in the direction it's heading (its angle) @@ -84,6 +87,9 @@ def move(self): def rotate(self,posNeg): """Rotates ship""" self.nImage,self.rect = rot_center(self.oImage,posNeg*3+(270-self.angle)) + w,h = self.nImage.get_size() + self.rect.inflate_ip(-30,-30) + self.rect.center = (self.x,self.y) self.angle -= posNeg*3 def update(self): @@ -91,6 +97,13 @@ def update(self): Does magic and makes the ship work. Updates position """ + if(self.score > 10000 * self.extraLives): + self.lives += 1 + self.extraLives += 1 + if(self.destroyed): + self.counter += 1 + if(self.counter == 120): + self.destroyed = False width,height = self.gD.get_size() speed = sqrt(self.x_speed**2+self.y_speed**2) # print(speed) @@ -119,6 +132,7 @@ def update(self): self.y = height self.rect.center = (self.x,self.y) + pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing self.gD.blit(self.nImage,self.rect) #pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing) def shoot(self,AllThings): @@ -126,12 +140,15 @@ def shoot(self,AllThings): y = self.y + int(5 * sin(self.angle)) AllThings.Projectiles.addProjectile(x,y,radians(self.angle),"Ship") def destroy(self): + self.destroyed = True self.lives = self.lives - 1 # right now just a test, need to put something else here self.x = self.startingX self.y = self.startingY self.angle = self.startingAngle + self.rotate(0) self.x_speed = 0 self.y_speed = 0 + self.counter = 0 class Asteroid(): """ Asteroid Class: @@ -342,13 +359,16 @@ def addProjectile(self,x,y,direction,alliance): # with the x,y and directions of the ship (with an offset bc of the front of the ship and that the origin is top left) def update(self): ListToDelete = [] # initializes the indices of what to delete + ListOfRects = [] for i in range(len(self.listOfProjectiles)): if(self.listOfProjectiles[i].destroyed): ListToDelete.append(i) # adding the index of destroyed particles to delete else: self.listOfProjectiles[i].update() + ListOfRects.append(self.listOfProjectiles[i].rect) for j in reversed(ListToDelete): del self.listOfProjectiles[j] + self.listOfRects = ListOfRects class UFO(): def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.y = y @@ -462,7 +482,7 @@ def update(self): #self.UFOs.listOfUFOs[collisionsUFO].destroy() #destroy both the asteroid and the projectile. self.ship.destroy() collisionsProj = self.ship.rect.collidelist(self.Projectiles.listOfRects) - if (collisionsProj != -1): + if (collisionsProj != -1 and self.Projectiles.listOfProjectiles[collisionsProj].alliance != "Ship"): self.Projectiles.listOfProjectiles[collisionsProj].destroy() self.ship.destroy() for i in self.Projectiles.listOfProjectiles: # runs through each projectile From 4dd40964a1940f9ded6eb2ec597e4c9aee15ab3f Mon Sep 17 00:00:00 2001 From: nathanestill Date: Thu, 15 Mar 2018 20:37:18 -0400 Subject: [PATCH 36/45] fixed ship hit box --- classes.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/classes.py b/classes.py index b22e7c06..6963ca83 100644 --- a/classes.py +++ b/classes.py @@ -69,7 +69,10 @@ def __init__(self,x,y,angle,img,gD): self.nImage = img self.w,self.h = img.get_size() self.gD = gD - self.rect = img.get_rect().inflate(-30,-30) + self.rect = img.get_rect() + self.changex = self.rect.w / 2 + self.changey = self.rect.h / 2 + self.rect.inflate_ip(-self.changex,-self.changey) self.rect.center = (self.x,self.y) self.score = 0 self.lives = 3 @@ -87,8 +90,9 @@ def move(self): def rotate(self,posNeg): """Rotates ship""" self.nImage,self.rect = rot_center(self.oImage,posNeg*3+(270-self.angle)) - w,h = self.nImage.get_size() - self.rect.inflate_ip(-30,-30) + self.changex = self.rect.w / 2 + self.changey = self.rect.h / 2 + self.rect.inflate_ip(-self.changex,-self.changey) self.rect.center = (self.x,self.y) self.angle -= posNeg*3 @@ -130,10 +134,10 @@ def update(self): self.y = 0 - self.h elif(self.y <= 0 - self.h): self.y = height - self.rect.center = (self.x,self.y) - pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing - self.gD.blit(self.nImage,self.rect) + #self.nImage.center = (self.x,self.y) + #pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing + self.gD.blit(self.nImage,(self.rect.x - self.changex / 2, self.rect.y - self.changey / 2)) #pygame.draw.rect(self.gD,(255,0,255),self.rect) # display's the ship's hit box in purple (for testing) def shoot(self,AllThings): x = self.x + int(5 * cos(self.angle)) @@ -478,11 +482,11 @@ def update(self): self.Asteroids.listOfAsteroids += self.Asteroids.listOfAsteroids[collisionsAster].destroy() #destroy both the asteroid and the projectile. self.ship.destroy() collisionsUFO = self.ship.rect.collidelist(self.UFOs.listOfRects) - if (collisionsUFO != -1): # if there is a collision + if (collisionsUFO != -1 and self.ship.destroyed == False): # if there is a collision #self.UFOs.listOfUFOs[collisionsUFO].destroy() #destroy both the asteroid and the projectile. self.ship.destroy() collisionsProj = self.ship.rect.collidelist(self.Projectiles.listOfRects) - if (collisionsProj != -1 and self.Projectiles.listOfProjectiles[collisionsProj].alliance != "Ship"): + if (collisionsProj != -1 and self.Projectiles.listOfProjectiles[collisionsProj].alliance != "Ship" and self.ship.destroyed == False): self.Projectiles.listOfProjectiles[collisionsProj].destroy() self.ship.destroy() for i in self.Projectiles.listOfProjectiles: # runs through each projectile From bd3e1e8fe9020e7fff1e4f878a0be5cac725ab29 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Fri, 16 Mar 2018 00:38:49 -0400 Subject: [PATCH 37/45] added a ton of headers to all my functions and classes that I should have done a long time ago --- classes.py | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 4 deletions(-) diff --git a/classes.py b/classes.py index 6963ca83..8ead26d5 100644 --- a/classes.py +++ b/classes.py @@ -262,11 +262,20 @@ def destroy(self): self.destroyed = True return [] class CollectionOfAsteroids(): + """ + A collection of the Asteroids in the game + listOfAsteroids - a list of the asteroids in the game + listOfRects - a list of the hitboxes of the asteroids + gameDisplay - the display + """ def __init__(self,gameDisplay): self.listOfAsteroids = [] self.gameDisplay = gameDisplay self.speed = 1 def spawnAsteroids(self,numberOfAsteroids): + """ + spawns a set number of asteroids in the sides of the game + """ width, height = self.gameDisplay.get_size() listOfAsteroids = [] # initializes a list of asteroids to update listOfRects = [] # initializes a list of hitboxes @@ -292,6 +301,9 @@ def spawnAsteroids(self,numberOfAsteroids): self.listOfAsteroids = listOfAsteroids self.listOfRects = listOfRects def update(self): + """ + updates all the asteroids, deleting them from the list if they are destroyed. + """ listOfRects = [] # asteroid ListToDelete = [] # a list that incluedes the indicies of what to delete for i in range(len(self.listOfAsteroids)): @@ -303,7 +315,10 @@ def update(self): for j in reversed(ListToDelete): # reversed so that it doesn't delete one and shift mid for loop. del self.listOfAsteroids[j] self.listOfRects = listOfRects - def destroyAll(self): # function for testingasteroid, not for the real game + def destroyAll(self): + """ + function for testingasteroid, not for the real game + """ sizeOfAsteroids = range(len(self.listOfAsteroids)) for i in sizeOfAsteroids: newAsteroid = self.listOfAsteroids[i].destroy() @@ -312,6 +327,18 @@ def destroyAll(self): # function for testingasteroid, not for the real game for i in sizeOfAsteroids: self.listOfAsteroids.pop(0) class Projectile(): + """ + projectiles that fire and destroy asteroids, ufos and players. + x - position x + y - position y + w, h - size of the projectiles + speed - speed of the projectile + direction- direction given to the projectiles + rect - the hitbox of the projectile + gameDisplay - the display + destroyed - senses whether the projectile is destroyed or not + distanceTravelled - detects how far the projectile has travelled + """ def __init__(self,x,y,direction,alliance,gameDisplay): size = 3 self.x = x @@ -333,6 +360,9 @@ def __init__(self,x,y,direction,alliance,gameDisplay): self.distanceWanted = 3/8 * height self.alliance = alliance def update(self): + """ + updates the position of the particle + """ if(self.distanceTravelled < self.distanceWanted): # if the projectile has travelled farther than the wanted distance, it destroys itself width, height = self.gameDisplay.get_size() # gets the display's width and length self.x = self.x + (self.speed * cos(self.direction)) # Sets the speed to a small change in space @@ -354,14 +384,26 @@ def update(self): def destroy(self): self.destroyed = True class CollectionOfProjectiles(): + """ + A collection of the Projectiles in the game + listOfProjectiles - a list of the asteroids in the game + listOfRects - a list of the hitboxes + gameDisplay - the display + """ def __init__(self,gameDisplay): self.listOfProjectiles = [] #initializes the asteroidprojectiles self.listOfRects = [] # initializes their hitboxes self.gameDisplay = gameDisplay def addProjectile(self,x,y,direction,alliance): + """ + Adds a projectile to the game at the given x y and direction with an alliance of either "UFO" or "Ship" + """ self.listOfProjectiles.append(Projectile(x,y,direction,alliance,self.gameDisplay)) # The spacebar command should call this # with the x,y and directions of the ship (with an offset bc of the front of the ship and that the origin is top left) def update(self): + """ + Updates all of the projectiles + """ ListToDelete = [] # initializes the indices of what to delete ListOfRects = [] for i in range(len(self.listOfProjectiles)): @@ -374,6 +416,20 @@ def update(self): del self.listOfProjectiles[j] self.listOfRects = ListOfRects class UFO(): + """ + A class of the general UFO, that moves autonomously and shoots + (we didn't have enough time to implement a second UFO, so there is only one type of UFO) + x - x position + y - y position + speed - speed of the ufo, constant + destroyed - whether the UFO is destroyed or not + image - the UFO image + w,h - the height and width of the image + FacingRight - the direction the UFO is facing(UFO goes either right to left or left to right)(also determines x position) + counter - for recording the refractory period of the shooting + listOfProjectiles - to allow it to call the add projectile function + straight - whether the UFO goes straight across the screen or down then up + """ def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.y = y self.speed = 2 @@ -392,17 +448,20 @@ def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): else: self.x = width def update(self): + """ + updates the position of the UFO, as well as deciding when to shoot + """ if(self.counter % self.fireRate == 0): self.shoot() self.counter += 1 width, height = self.gameDisplay.get_size() - if(self.straight == True): + if(self.straight == True): # sometimes it goes straight accross, sometimes down then up if(self.FacingRight): self.direction = 0 else: self.direction = pi else: - if(self.FacingRight): + if(self.FacingRight): # algorithm for going down then up if((self.x + self.w / 2) < width * 1 / 4): self.direction = 0 elif(self.x + self.w / 2 < width / 2): @@ -427,11 +486,19 @@ def update(self): elif(self.y <= 0 - self.h): # same as above (makes it so that the whole image has to leave the screen for it to go to the other side) self.y = height self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) - #pygame.draw.rect(self.gameDisplay,(0,0,255),self.rect) # display's the asteroid's hit box in red (for testing) + #pygame.draw.rect(self.gameDisplay,(0,0,255),self.rect) # display's the UFO's hit box in blue (for testing) self.gameDisplay.blit(self.image,(self.x,self.y)) def destroy(self): + """ + destroys the UFO + """ self.destroyed = True class BigUFO(UFO): + """ + A subclass of UFO that shoots in a random direction and moves either straight or down then up + shrinkage - how much to shrink the UFO image + fireRate - cooldown for how often the UFO fires + """ def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): super().__init__(y,FacingRight,gameDisplay,listOfProjectiles) self.image = pygame.transform.scale(self.image,(self.w // 2,self.h // 2)) @@ -440,21 +507,37 @@ def __init__(self,y,FacingRight,gameDisplay,listOfProjectiles): self.rect = pygame.Rect((self.x + self.shrinkage / 2,self.y + self.shrinkage / 2),(self.w - self.shrinkage,self.h - self.shrinkage)) self.fireRate = 60 def shoot(self): + """ + shoots a projectile + """ if(not self.destroyed): self.listOfProjectiles.addProjectile(self.x + self.w / 2,self.y + self.h / 2,random.uniform(0,2*pi),"UFO") class CollectionOfUFOs(): + """ + A collection of the UFOs on the screen(there can only be one UFO, but this allows for an opportunity to add more if the game is too easy) + listOfUFOs - the list of the UFOs on screen + listOfRects - the list of the hitboxes of UFOs + gameDisplay - display + listOfProjectiles - the list of projectiles on screen so UFOs can shoot + """ def __init__(self,gameDisplay,listOfProjectiles): self.listOfUFOs = [] #initializes the projectiles self.listOfRects = [] # initializes their hitboxes self.gameDisplay = gameDisplay self.listOfProjectiles = listOfProjectiles def spawnBigUFO(self): + """ + Spawns a big UFO in the game (would have been complemented by a spawnSmallUFO if time alloted) + """ width, height = self.gameDisplay.get_size() sampleUFO = BigUFO(0,True,self.gameDisplay,self.listOfProjectiles) y = random.randint(-sampleUFO.h // 2,height - sampleUFO.h // 2) facingRight = bool(random.getrandbits(1)) self.listOfUFOs.append(BigUFO(y,facingRight,self.gameDisplay,self.listOfProjectiles)) def update(self): + """ + updates the list of UFOs + """ listOfRects = [] ListToDelete = [] # initializes the indices of what to delete for i in range(len(self.listOfUFOs)): @@ -467,6 +550,14 @@ def update(self): del self.listOfUFOs[j] self.listOfRects = listOfRects class listOfObjects(): + """ + List of all objects in the game: + gameDisplay - display + Asteroids - the collection of Asteroids + Projectiles - the collection of Projectiles + UFOs - the collection of UFOs + ship - the ship in the game + """ def __init__(self,gameDisplay, ship): self.gameDisplay = gameDisplay self.Asteroids = CollectionOfAsteroids(gameDisplay) @@ -474,6 +565,9 @@ def __init__(self,gameDisplay, ship): self.UFOs = CollectionOfUFOs(gameDisplay,self.Projectiles) self.ship = ship def update(self): + """ + updates all objects and handles any collinion detection between objects + """ self.Asteroids.update() self.UFOs.update() self.Projectiles.update() From 856925fe7eacfc344255f8d7efc7b41b2b98ef70 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Fri, 16 Mar 2018 11:36:10 -0400 Subject: [PATCH 38/45] added Results markdown --- FullGame.png | Bin 0 -> 14279 bytes ProjectReflection.md | 6 ++++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 FullGame.png diff --git a/FullGame.png b/FullGame.png new file mode 100644 index 0000000000000000000000000000000000000000..2e193ebd0143ff19e9ad51ef7bef4c55e695995d GIT binary patch literal 14279 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

U@{e)K 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 Date: Fri, 16 Mar 2018 11:38:14 -0400 Subject: [PATCH 39/45] Add GAMEOVER screen -Added functionality to prevent ship from respawning after lives==0 -key 'r' to toggle rapid fire -key 't' to add lives --- classes.py | 18 ++++++++++++++---- interface.py | 17 +++++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/classes.py b/classes.py index 8ead26d5..9bc2893a 100644 --- a/classes.py +++ b/classes.py @@ -6,7 +6,7 @@ class GUI(): WHITE = (255,255,255) font = pygame.font.SysFont("couriernew",32) - bx = 150 + bx = 700 by = 100 def __init__(self,gD): @@ -15,16 +15,26 @@ def __init__(self,gD): def update(self,ship): box = pygame.surface.Surface((self.bx, self.by)) txt_surf = self.font.render(str(ship.score), True, self.WHITE) # bottom line - txt_rect = txt_surf.get_rect(center=(self.bx//2, 40)) + txt_rect = txt_surf.get_rect(center=(75, 40)) box.blit(txt_surf, txt_rect) w,h = ship.oImage.get_size() txt_surf = pygame.transform.scale(ship.oImage,(int(w*.5),int(h*.5))) for x in range(ship.lives): spacing = x*45 - txt_rect = txt_surf.get_rect(center=(self.bx//2-45+spacing, 90)) + txt_rect = txt_surf.get_rect(center=(75-45+spacing, 90)) box.blit(txt_surf, txt_rect) self.gD.blit(box,(0,0)) - # self.bx//2, 70) + + def gameOver(self,ship): + box = pygame.surface.Surface((300,500)) + gO = self.font.render("GAME OVER", True,self.WHITE) + gO_rect = gO.get_rect(center=(90,90)) + box.blit(gO,gO_rect) + txt_surf = self.font.render(str(ship.score), True, self.WHITE) # bottom line + txt_rect = txt_surf.get_rect(center=(90, 200)) + box.blit(txt_surf,txt_rect) + w,h = self.gD.get_size() + self.gD.blit(box,(int(w/2)-90,int(h/2)-90-40)) def rot_center(image, angle): diff --git a/interface.py b/interface.py index ce1040e2..f141f56b 100644 --- a/interface.py +++ b/interface.py @@ -48,6 +48,7 @@ """ initialize the ship to be able to shoot""" canShoot = True +shoot_count = 20 while running: @@ -59,6 +60,13 @@ if event.type == pygame.KEYUP: if event.key == pygame.K_q: running = False + if event.key == pygame.K_t: + ship.lives += 1 + if event.key == pygame.K_r: + if shoot_count == 20: + shoot_count = 2 + elif shoot_count == 2: + shoot_count = 20 """ player interface """ keys_pressed = pygame.key.get_pressed() if keys_pressed[pygame.K_UP]: @@ -73,7 +81,7 @@ counter = 0 else: counter += 1 - if(counter >= 20): + if(counter >= shoot_count): canShoot = True if keys_pressed[pygame.K_SPACE]: if(canShoot): @@ -93,10 +101,15 @@ gameDisplay.fill(black) + gui.update(ship) - ship.update() + if ship.lives > 0: + ship.update() AllThings.update() + if ship.lives == 0: + gui.gameOver(ship) + pygame.display.update() clock.tick(60) From d5729cda4a2047ad1fce6b0a17e6dee935d5559a Mon Sep 17 00:00:00 2001 From: nathanestill Date: Fri, 16 Mar 2018 12:10:44 -0400 Subject: [PATCH 40/45] adding my implementation --- Asteroid.py | 2 +- ProjectReflection.md | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Asteroid.py b/Asteroid.py index e8978c77..6a238097 100644 --- a/Asteroid.py +++ b/Asteroid.py @@ -195,7 +195,7 @@ def __init__(self,x,y,direction,alliance,gameDisplay): self.direction = direction self.rect = ((self.x,self.y),(size,size)) self.image = pygame.Surface((size,size)) - self.image.fill((255,255,255)) + self.image.fill((255,165,0)) self.gameDisplay = gameDisplay self.destroyed = False self.distanceTravelled = 0 # asteroids diff --git a/ProjectReflection.md b/ProjectReflection.md index 90fa9244..2661afa8 100644 --- a/ProjectReflection.md +++ b/ProjectReflection.md @@ -13,7 +13,22 @@ The asteroids spawn in random places around the map and break up when hit with a ![A screen shot of the game working](FullGame.png) ## Implementation [~2-3 paragraphs + UML diagram] - +Our implementation for the non-controllable objects consisted of making a class for each object. Each class had an update function that handled the movement of the object and a destroy function, for when the object was destroyed. The asteroid and UFO had subclasses that inherited them, one for each size of asteroid, and one for each type of asteroid (We had initially planned to add a second type of UFO, but ran out of time). Each of these classes had an overarching class that contained all of the instances of the lower class. This made collision detection much easier and allowed us to simply update the greater class, which in turn updated all of the instances. There was one class that contained all of the objects in the game, holding the overarching classes for each object. This class handled collision detection and updated all of the objects. + +Class Diagram +* listOfObjects - contains and keeps track of all objects + * listOfAsteroids - contains and keeps track of all asteroids + * Asteroid - Base Asteroid class + * Small Asteroid - Inherits from Asteroid + * Medium Asteroid - Inherits from Asteroid + * Large Asteroid - Inherits from Asteroid + * listOfUFOs - contains and keeps track of all UFOs + * UFO - Base UFO class + * BigUFO - Inherits from UFO + * SmallUFO (not implemented) - Inherits from UFO + * listOfProjectiles - contains and keeps track of all Projectiles + * Projectile - Base Projectile class + * Ship ## Reflection [~2 paragraphs] From 25b6cd484031488c27bdfae81d0415744b3e8f6e Mon Sep 17 00:00:00 2001 From: Corey Date: Fri, 16 Mar 2018 12:11:56 -0400 Subject: [PATCH 41/45] Updated project reflection --- ProjectReflection.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/ProjectReflection.md b/ProjectReflection.md index 2661afa8..80e3ee3c 100644 --- a/ProjectReflection.md +++ b/ProjectReflection.md @@ -1,11 +1,11 @@ # Project Reflection ### Authors: Corey Cochran-Lepiz, Nathan Estill -## Project Overview [max 100 words] +## Project Overview We created a Pygame version of the classic arcade game, Asteroids. -## Results [~2-3 paragraphs + figures/examples] +## Results We ended up with a game that does a good job resembling the original game. The player starts with three lives. They have a ship that moves with an acceleration and turning based system. The ship slows down when not accelerating and can "drift" when turning while going forward. Colliding with asteroids or UFOs, or getting hit by the UFOs projectile makes the player lose a life. The ship shoots a projectile that goes about 5/8 of the size of the screen. Hitting other objects with the ship's projectiles grants points depending on the object. No other interactions grant points. For every 10000 points the player receives, another life is granted. @@ -29,18 +29,12 @@ Class Diagram * listOfProjectiles - contains and keeps track of all Projectiles * Projectile - Base Projectile class * Ship + ## Reflection [~2 paragraphs] + +      Looking back at the project we both felt like it was a great success. We feel like the project was scoped well for where our skill levels are. We weren't completely comfortable going into it but at the same time we didn't spend hours on hours debugging code. At the beginning of the project we sat down one lunch with a white board to talk about the overarching design goals we had for the project, written [here](keepInMind.md), which was a great start as it meant we had laid out the project as well as all of the responsibilities. We decided to go with the 'divide and conquer' approach alongside meeting every few days to work next to each other which turned out to be an effective strategy for us. I wish we had brainstormed ways to go above and beyond with the project early on so that we could have implemented them from the start. One of the ideas being a two-player Asteroids where one person drives and another aims and shoots a canon. -Please prepare a short document (~1 page not including figures) with the following sections: - -Project Overview [Maximum 100 words] - -Write a short abstract describing your project. - -Results [~2-3 paragraphs + figures/examples] - -Present what you accomplished. This will be different for each project, but screenshots are likely to be helpful. Implementation [~2-3 paragraphs + UML diagram] From a3645337d01c272daebb8a0d3c830b153520b8b7 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Fri, 16 Mar 2018 12:20:27 -0400 Subject: [PATCH 42/45] made a few changes to the reflection --- ProjectReflection.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ProjectReflection.md b/ProjectReflection.md index 80e3ee3c..4dd44ba3 100644 --- a/ProjectReflection.md +++ b/ProjectReflection.md @@ -17,22 +17,26 @@ Our implementation for the non-controllable objects consisted of making a class Class Diagram * listOfObjects - contains and keeps track of all objects - * listOfAsteroids - contains and keeps track of all asteroids + * CollectionOfAsteroids - contains and keeps track of all asteroids * Asteroid - Base Asteroid class * Small Asteroid - Inherits from Asteroid * Medium Asteroid - Inherits from Asteroid * Large Asteroid - Inherits from Asteroid - * listOfUFOs - contains and keeps track of all UFOs + * CollectionOfUFOs - contains and keeps track of all UFOs * UFO - Base UFO class * BigUFO - Inherits from UFO * SmallUFO (not implemented) - Inherits from UFO - * listOfProjectiles - contains and keeps track of all Projectiles + * CollectionOfProjectiles - contains and keeps track of all Projectiles * Projectile - Base Projectile class * Ship - + ## Reflection [~2 paragraphs] -      Looking back at the project we both felt like it was a great success. We feel like the project was scoped well for where our skill levels are. We weren't completely comfortable going into it but at the same time we didn't spend hours on hours debugging code. At the beginning of the project we sat down one lunch with a white board to talk about the overarching design goals we had for the project, written [here](keepInMind.md), which was a great start as it meant we had laid out the project as well as all of the responsibilities. We decided to go with the 'divide and conquer' approach alongside meeting every few days to work next to each other which turned out to be an effective strategy for us. I wish we had brainstormed ways to go above and beyond with the project early on so that we could have implemented them from the start. One of the ideas being a two-player Asteroids where one person drives and another aims and shoots a canon. +      Looking back at the project we both felt like it was a great success. We feel like the project was scoped well for where our skill levels are. We weren't completely comfortable going into it but at the same time we didn't spend hours on hours debugging code. At the beginning of the project we sat down one dinner with a white board to talk about the overarching design goals we had for the project, written [here](keepInMind.md), which was a great start as it meant we had laid out the project as well as all of the responsibilities. We decided to go with the 'divide and conquer' approach alongside meeting every few days to work next to each other for a few hours which turned out to be an effective strategy for us. We wish we had brainstormed ways to go above and beyond with the project early on so that we could have implemented them from the start. One of the ideas being a two-player Asteroids where one person drives and another aims and shoots a canon. + +Looking back, we could have made a lot more of the classes inherit from each other. We could have made a class that was a basic object that moved in space that all of the other objects could have inherited from. We also could have made a class that the could have been a base for all of the 'collection' classes that would have made that part go smoother. + + From 949fa3f44e5da23af9b9ce8196bd6fc61435de65 Mon Sep 17 00:00:00 2001 From: Corey Date: Fri, 16 Mar 2018 12:34:44 -0400 Subject: [PATCH 43/45] Updated reflection --- ProjectReflection.md | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/ProjectReflection.md b/ProjectReflection.md index 4dd44ba3..60ab256a 100644 --- a/ProjectReflection.md +++ b/ProjectReflection.md @@ -7,13 +7,16 @@ We created a Pygame version of the classic arcade game, Asteroids. ## Results -We ended up with a game that does a good job resembling the original game. The player starts with three lives. They have a ship that moves with an acceleration and turning based system. The ship slows down when not accelerating and can "drift" when turning while going forward. Colliding with asteroids or UFOs, or getting hit by the UFOs projectile makes the player lose a life. The ship shoots a projectile that goes about 5/8 of the size of the screen. Hitting other objects with the ship's projectiles grants points depending on the object. No other interactions grant points. For every 10000 points the player receives, another life is granted. +      We ended up with a game that does a good job resembling the original game. The player starts with three lives. They have a ship that moves with an acceleration and turning based system. The ship slows down when not accelerating and can "drift" when turning while going forward. Colliding with asteroids or UFOs, or getting hit by the UFOs projectile makes the player lose a life. The ship shoots a projectile that goes about 5/8 of the size of the screen. Hitting other objects with the ship's projectiles grants points depending on the object. No other interactions grant points. For every 10000 points the player receives, another life is granted. -The asteroids spawn in random places around the map and break up when hit with a non-asteroid object. They break up twice into two more smaller asteroids and disappear on the third hit. Large asteroids are worth 20 points, medium asteroids are worth 50 and small asteroids are worth 100. The UFOs spawn randomly throughout the game. They move in either a straight line or a in a up and down fashion. They shoot in random directions at a distance that is lower than that of the Ship's projectiles. UFOs can shoot asteroids and hit asteroids, but does not grant points if destroyed in this manner. The UFO is worth 500 points. +      The asteroids spawn in random places around the map and break up when hit with a non-asteroid object. They break up twice into two more smaller asteroids and disappear on the third hit. Large asteroids are worth 20 points, medium asteroids are worth 50 and small asteroids are worth 100. The UFOs spawn randomly throughout the game. They move in either a straight line or a in a up and down fashion. They shoot in random directions at a distance that is lower than that of the Ship's projectiles. UFOs can shoot asteroids and hit asteroids, but does not grant points if destroyed in this manner. The UFO is worth 500 points. ![A screen shot of the game working](FullGame.png) ## Implementation [~2-3 paragraphs + UML diagram] -Our implementation for the non-controllable objects consisted of making a class for each object. Each class had an update function that handled the movement of the object and a destroy function, for when the object was destroyed. The asteroid and UFO had subclasses that inherited them, one for each size of asteroid, and one for each type of asteroid (We had initially planned to add a second type of UFO, but ran out of time). Each of these classes had an overarching class that contained all of the instances of the lower class. This made collision detection much easier and allowed us to simply update the greater class, which in turn updated all of the instances. There was one class that contained all of the objects in the game, holding the overarching classes for each object. This class handled collision detection and updated all of the objects. +      Our implementation for the non-controllable objects consisted of making a class for each object. Each class had an update function that handled the movement of the object and a destroy function, for when the object was destroyed. The asteroid and UFO had subclasses that inherited them, one for each size of asteroid, and one for each type of asteroid (We had initially planned to add a second type of UFO, but ran out of time). Each of these classes had an overarching class that contained all of the instances of the lower class. This made collision detection much easier and allowed us to simply update the greater class, which in turn updated all of the instances. There was one class that contained all of the objects in the game, holding the overarching classes for each object. This class handled collision detection and updated all of the objects. + +      On the decision decisions. For the Ship class we decided to go with Pygame's rotation function which was tricky since each time it rotates an image it loses overall quality. Another route we could have gone is making a folder with every angle of the ship inside of it so that all it had to do was pull from the folder when we called for a rotation instead of modifying an image each time. + Class Diagram * listOfObjects - contains and keeps track of all objects @@ -28,24 +31,11 @@ Class Diagram * SmallUFO (not implemented) - Inherits from UFO * CollectionOfProjectiles - contains and keeps track of all Projectiles * Projectile - Base Projectile class - * Ship + * Ship - kept all data for the player + * GUI - in charge of all user interface realated things ## Reflection [~2 paragraphs]       Looking back at the project we both felt like it was a great success. We feel like the project was scoped well for where our skill levels are. We weren't completely comfortable going into it but at the same time we didn't spend hours on hours debugging code. At the beginning of the project we sat down one dinner with a white board to talk about the overarching design goals we had for the project, written [here](keepInMind.md), which was a great start as it meant we had laid out the project as well as all of the responsibilities. We decided to go with the 'divide and conquer' approach alongside meeting every few days to work next to each other for a few hours which turned out to be an effective strategy for us. We wish we had brainstormed ways to go above and beyond with the project early on so that we could have implemented them from the start. One of the ideas being a two-player Asteroids where one person drives and another aims and shoots a canon. Looking back, we could have made a lot more of the classes inherit from each other. We could have made a class that was a basic object that moved in space that all of the other objects could have inherited from. We also could have made a class that the could have been a base for all of the 'collection' classes that would have made that part go smoother. - - - - - -Implementation [~2-3 paragraphs + UML diagram] - -Describe your implementation at a system architecture level. Include a UML class diagram, and talk about the major components, algorithms, data structures and how they fit together. You should also discuss at least one design decision where you had to choose between multiple alternatives, and explain why you made the choice you did. - -Reflection [~2 paragraphs] - -From a process point of view, what went well? What could you improve? Other possible reflection topics: Was your project appropriately scoped? Did you have a good plan for unit testing? How will you use what you learned going forward? What do you wish you knew before you started that would have helped you succeed? - -Also discuss your team process in your reflection. How did you plan to divide the work (e.g. split by class, always pair program together, etc.) and how did it actually happen? Were there any issues that arose while working together, and how did you address them? What would you do differently next time? From d3844de1b55e0ea4fde225b920e5bad6126389c4 Mon Sep 17 00:00:00 2001 From: nathanestill Date: Fri, 16 Mar 2018 12:38:25 -0400 Subject: [PATCH 44/45] adding my design choice and how to play --- ProjectReflection.md | 5 ++--- README.md | 11 ++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ProjectReflection.md b/ProjectReflection.md index 60ab256a..0256384e 100644 --- a/ProjectReflection.md +++ b/ProjectReflection.md @@ -15,8 +15,7 @@ We created a Pygame version of the classic arcade game, Asteroids. ## Implementation [~2-3 paragraphs + UML diagram]       Our implementation for the non-controllable objects consisted of making a class for each object. Each class had an update function that handled the movement of the object and a destroy function, for when the object was destroyed. The asteroid and UFO had subclasses that inherited them, one for each size of asteroid, and one for each type of asteroid (We had initially planned to add a second type of UFO, but ran out of time). Each of these classes had an overarching class that contained all of the instances of the lower class. This made collision detection much easier and allowed us to simply update the greater class, which in turn updated all of the instances. There was one class that contained all of the objects in the game, holding the overarching classes for each object. This class handled collision detection and updated all of the objects. -      On the decision decisions. For the Ship class we decided to go with Pygame's rotation function which was tricky since each time it rotates an image it loses overall quality. Another route we could have gone is making a folder with every angle of the ship inside of it so that all it had to do was pull from the folder when we called for a rotation instead of modifying an image each time. - +      On the design choices. For the Ship class we decided to go with Pygame's rotation function which was tricky since each time it rotates an image it loses overall quality. Another route we could have gone is making a folder with every angle of the ship inside of it so that all it had to do was pull from the folder when we called for a rotation instead of modifying an image each time. Another design choice we made was to connect surfaces to rectangles that approximately represented their shape. We could have made many smaller rectangles to more accurately represent the shape of the object, but we decided that it wasn't worth the additional time spent. The estimated hit boxes are close enough, and the additional accuracy would have made an insignificant improvement. Class Diagram * listOfObjects - contains and keeps track of all objects @@ -32,7 +31,7 @@ Class Diagram * CollectionOfProjectiles - contains and keeps track of all Projectiles * Projectile - Base Projectile class * Ship - kept all data for the player - * GUI - in charge of all user interface realated things + * GUI - in charge of all user interface realated things ## Reflection [~2 paragraphs] diff --git a/README.md b/README.md index 5f822327..4c60d462 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,11 @@ # InteractiveProgramming -This is the base repo for the interactive programming project for Software Design, Spring 2018 at Olin College. +run python3 interface.py +How to play: +Up key: Move the ship forward +Left/Right Key: rotates the ship +Space Bar: Shoot (can be held down) +Q: quits the game + +Cheat Codes: +R: Rapid Fire Mode (Toggle) +L: Add life From 64e3756f50ff14e61d27faeaf0354244ea38ab94 Mon Sep 17 00:00:00 2001 From: Corey Date: Fri, 16 Mar 2018 13:08:45 -0400 Subject: [PATCH 45/45] Changed main to qbert.py --- qbert.py | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 qbert.py diff --git a/qbert.py b/qbert.py new file mode 100644 index 00000000..f141f56b --- /dev/null +++ b/qbert.py @@ -0,0 +1,117 @@ +""" +Asteroids via Pygame + +@authors coreyacl & nathanestill + +""" + +import pygame +from math import cos,sin,sqrt,radians,atan,pi +from classes import * +import time +import random + + +""" initiate pygame """ +pygame.init() + +""" initiate screen """ +display_width = 1600 +display_height = 1200 +imgScale = .13 +gameDisplay = pygame.display.set_mode((display_width,display_height)) +pygame.display.set_caption("Asteroids") +black = (0,0,0) +white = (255,255,255) + +""" some other important things """ +clock = pygame.time.Clock() +running = True + +""" initiate ship object """ +shipImg = pygame.image.load('spa1.png') +shipX = (display_width * .5) +shipY = (display_height * .5) +w,h = shipImg.get_size() +shipImg = pygame.transform.scale(shipImg,(int(w*imgScale),int(h*imgScale))) +ship = Ship(shipX,shipY,270,shipImg,gameDisplay) + +""" initiate asteroids and UFOs """ +numberOfAsteroids = 4 +AllThings = listOfObjects(gameDisplay,ship) +AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) +AllThings.UFOs.spawnBigUFO() +AllThings.update() # testing the many asteroids spawn in the right spot + +""" initiate GUI """ +gui = GUI(gameDisplay) + +""" initialize the ship to be able to shoot""" +canShoot = True +shoot_count = 20 + +while running: + + """ listens to events and does stuff """ + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + # print(event) + if event.type == pygame.KEYUP: + if event.key == pygame.K_q: + running = False + if event.key == pygame.K_t: + ship.lives += 1 + if event.key == pygame.K_r: + if shoot_count == 20: + shoot_count = 2 + elif shoot_count == 2: + shoot_count = 20 + """ player interface """ + keys_pressed = pygame.key.get_pressed() + if keys_pressed[pygame.K_UP]: + ship.move() + else: + ship.drift = True + if keys_pressed[pygame.K_LEFT]: + ship.rotate(1) + if keys_pressed[pygame.K_RIGHT]: + ship.rotate(-1) + if(canShoot): + counter = 0 + else: + counter += 1 + if(counter >= shoot_count): + canShoot = True + if keys_pressed[pygame.K_SPACE]: + if(canShoot): + ship.shoot(AllThings) + canShoot = False + counter = 0 + """ UFO spawning """ + randomInt = random.randint(1,1000) + if(randomInt == 1 and len(AllThings.UFOs.listOfUFOs) == 0): + AllThings.UFOs.spawnBigUFO() + + """ spawns new level """ + if(len(AllThings.Asteroids.listOfAsteroids) == 0 and len(AllThings.UFOs.listOfUFOs) == 0): + numberOfAsteroids += 1 + AllThings.Asteroids.spawnAsteroids(numberOfAsteroids) + + + + gameDisplay.fill(black) + + gui.update(ship) + if ship.lives > 0: + ship.update() + AllThings.update() + + if ship.lives == 0: + gui.gameOver(ship) + + pygame.display.update() + clock.tick(60) + +pygame.quit() +quit()