1
Fork 0

Compare commits

..

79 commits
V1.4 ... master

Author SHA1 Message Date
bb2bc41b68 Fixed unit number (facepalm) 2015-09-14 23:00:09 +01:00
8020853ef7 Moved files over to github 2015-09-14 22:57:43 +01:00
cb5ece304a removed thumbs files 2015-09-14 22:15:05 +01:00
Jake Howard
5640158e82 Initial commit 2015-09-14 22:12:57 +01:00
d91f82a889 fixed neverending loop 2015-06-04 12:34:22 +01:00
7cf6638cb9 forgot to disable main sound 2015-06-04 12:19:33 +01:00
5b14f36770 modified OP keyboard shortcuts for OP. 2015-06-04 12:19:22 +01:00
a9d7d9c6f7 fixed forgotten pass 2015-06-04 11:20:26 +01:00
230c2db7ec readded OP sound 2015-05-21 13:21:46 +01:00
8f56f52980 changed extension 2015-05-21 13:21:37 +01:00
0bbd172764 updated display 2015-05-21 13:21:28 +01:00
3542fe1f74 compressed audio 2015-05-21 13:21:18 +01:00
1d216164c8 Added window title 2015-05-21 13:09:43 +01:00
1b34829e62 changed font size 2015-05-21 13:08:46 +01:00
73a913c43c added branding 2015-05-21 12:58:31 +01:00
b4a8b7db3f updated version 2015-05-19 12:20:09 +01:00
e7687ded09 updated bug when resetting player image. It sent you to origin and you lost instantly 2015-05-19 12:19:47 +01:00
b30a7c4ff0 because windows 2015-05-19 12:19:16 +01:00
f278d9b103 updated levels 2015-05-19 12:19:06 +01:00
840e1d0b78 updated texture code and lives 2015-05-19 12:17:27 +01:00
33df9d2ecf added code for calling target image manually 2015-05-19 12:16:56 +01:00
cce185db01 added lives 2015-05-19 12:15:19 +01:00
852071900e added powerups to game 2015-05-19 12:13:44 +01:00
b166569da3 Added versions to game 2015-05-19 10:09:48 +01:00
TheOrangeOne
f9d90cd6ad README.md edited online with Bitbucket 2015-05-14 13:55:48 +00:00
TheOrangeOne
ffe7e0568b README.md edited online with Bitbucket 2015-05-14 13:54:47 +00:00
b6566b20ec added option to reset image 2015-05-14 13:21:54 +01:00
6ce5e0a463 You can now turn OP mode off 2015-05-14 13:21:10 +01:00
746a9b3389 changed basic instructions and requirements 2015-05-14 13:20:59 +01:00
a6c9e8100b rebranding the game 2015-05-14 13:20:33 +01:00
42d74daaf8 Flipped sound logic 2015-05-13 09:31:32 +01:00
51f8d3e4eb stop OP music when you press the button again 2015-05-13 09:31:08 +01:00
7ae0ca4d3f Lives go red at 1 not 0!! 2015-05-13 09:30:46 +01:00
c91a7e8359 changed sounds tickbox label 2015-05-13 09:30:30 +01:00
b08cf848fa updated default texture pack 2015-05-13 09:30:07 +01:00
f0b36b23d5 added extra import 2015-05-13 09:03:04 +01:00
TheOrangeOne
038fb7a72f README.md edited online with Bitbucket 2015-05-12 22:01:56 +00:00
TheOrangeOne
9c3cc001e8 README.md edited online with Bitbucket 2015-05-12 21:59:11 +00:00
b773930dd2 Moved player position and thresholds 2015-05-12 22:50:13 +01:00
3ba98e89a6 updated how often targets move 2015-05-12 22:49:33 +01:00
43883a0ee2 Made shooting with multiple buttons 2015-05-12 22:49:15 +01:00
cb82deed7b stop bug where multiple sounds play 2015-05-12 22:48:41 +01:00
0d4580c854 Sounds disabling 2015-05-12 22:48:12 +01:00
cea485736e changed starting sounds 2015-05-12 22:46:47 +01:00
1784865b1a updated HUD and colours 2015-05-12 22:46:08 +01:00
99ab88af18 changed window size to be more realistic to game 2015-05-12 22:45:51 +01:00
c0f78046ef imports 2015-05-12 22:45:19 +01:00
7475a69d2a changed movement of targets 2015-05-12 22:45:02 +01:00
11ff4cd502 space vs tabs 2015-05-12 22:44:40 +01:00
0bc944c284 Changed size of objects 2015-05-12 22:43:41 +01:00
07ecced10b Bullets are now on top of targets 2015-05-12 22:43:01 +01:00
1b44b11144 Allow more fine controls for main sound track 2015-05-12 22:42:46 +01:00
f8e2e5df71 Changed style for about button 2015-05-12 22:40:22 +01:00
a56dd547b9 Added toggles for sounds 2015-05-12 22:40:02 +01:00
613a4b36c7 Moved reset button 2015-05-12 22:39:40 +01:00
701f722f10 Moved target generation to targets file 2015-05-12 22:37:33 +01:00
55f3bdae15 Made scale smaller 2015-05-12 18:46:30 +01:00
9fb556cc7a changed styling of about button 2015-05-12 18:44:45 +01:00
e50d081004 I don't even CMD 2015-05-12 18:43:01 +01:00
5f4d456388 Changed Font Sizes 2015-05-12 18:42:05 +01:00
e34d53fdd4 updated FPS. Global variables are really messing up here... 2015-05-12 15:01:08 +01:00
3f25eb13b4 updated padding values 2015-05-12 15:00:50 +01:00
f7de3262d9 Updated options, and added about button 2015-05-12 14:59:41 +01:00
d005fd5a52 changed shooting occurance and speed, and changed logic 2015-05-12 14:07:52 +01:00
a0c1a77ef6 updated to make sure its all the enemies! 2015-05-12 14:07:31 +01:00
9196224a32 Added check if more shooters are given 2015-05-12 13:19:51 +01:00
ab74f0bcad changed padding value 2015-05-12 13:18:40 +01:00
e16ee98f04 added more levels! 2015-05-12 13:15:53 +01:00
cb4293370a stupid stupid stupid error 2015-05-12 13:07:57 +01:00
unknown
c627f7f13b REmoved possible bugs, and tabs vs spaces 2015-05-12 12:58:22 +01:00
00f6fd2e5e changed image 2015-05-12 12:18:01 +01:00
150efceafc bloody windows! 2015-05-12 12:17:49 +01:00
8d3a77a9c3 tabs vs spaces, and added texture changing code 2015-05-12 12:17:41 +01:00
e21781e586 tabs vs spaces, and added more texture code. 2015-05-12 12:16:59 +01:00
03de948eb4 tabs vs spaces, and updated logic to make it work (from last nights editing) 2015-05-12 12:16:27 +01:00
e34503d2bc updated texture code 2015-05-12 12:15:58 +01:00
a499534f11 no idea 2015-05-12 12:15:42 +01:00
fdd6994ce0 Added sound effects and music 2015-05-12 12:15:22 +01:00
9f7918ab0e Added textures 2015-05-12 12:14:33 +01:00
23 changed files with 523 additions and 325 deletions

56
.gitignore vendored
View file

@ -1 +1,57 @@
# Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/

79
GUI.py
View file

@ -1,21 +1,26 @@
from tkinter import * from tkinter import *
from tkinter.ttk import * from tkinter.ttk import *
import logging import logging
from os import system
import game import game
from assets import Textures
PADDING_TITLE = 15 PADDING_TITLE = 15
PADDING_BUTTON = 9 PADDING_BUTTON = 9
VERSION = {"ID":"2.2", "DATE": "19/05/15"}
class Main_Window: class Main_Window:
def __init__(self, master): def __init__(self, master):
self.master = master self.master = master
self.master.title("SPACE INVADERS") self.master.title("ATTACK ON BLOCKS")
self.title = Label(self.master) self.title = Label(self.master)
self.title.config(text="SPACE INVADERS!",font=("Courier New", 37)) self.title.config(text="ATTACK ON BLOCKS!",font=("Courier New", 37))
self.title.pack(side="top", padx=PADDING_BUTTON, pady=PADDING_TITLE/2) self.title.pack(side="top", padx=PADDING_TITLE, pady=PADDING_TITLE/2)
self.version_info = Label(self.master)
self.version_info.config(text="Version {ID} tagged {DATE}".format(**VERSION), font=("Courier New", 13))
self.version_info.pack(side="top", padx=0, pady=PADDING_BUTTON/2)
self.start_button = Button(self.master, style="Menu.TButton") self.start_button = Button(self.master, style="Menu.TButton")
self.start_button.config(text="Play Game") self.start_button.config(text="Play Game")
@ -27,13 +32,24 @@ class Main_Window:
self.options_button.pack(fill=BOTH, ipadx=PADDING_BUTTON/2, ipady=PADDING_BUTTON/2, padx=PADDING_BUTTON, pady=PADDING_BUTTON) self.options_button.pack(fill=BOTH, ipadx=PADDING_BUTTON/2, ipady=PADDING_BUTTON/2, padx=PADDING_BUTTON, pady=PADDING_BUTTON)
self.options_button.bind('<Button-1>', self.show_options) self.options_button.bind('<Button-1>', self.show_options)
self.help_button = Button(self.master, style="About.TButton")
self.help_button.config(text="About / Help")
self.help_button.pack(fill=BOTH, ipadx=PADDING_BUTTON/4, ipady=PADDING_BUTTON/4, padx=PADDING_BUTTON, pady=PADDING_BUTTON)
self.help_button.bind('<Button-1>', self.show_info)
self.exit_button = Button(self.master, style="Quit.TButton") self.exit_button = Button(self.master, style="Quit.TButton")
self.exit_button.config(text="Quit Game") self.exit_button.config(text="Quit Game")
self.exit_button.pack(ipadx=PADDING_BUTTON/3, ipady=PADDING_BUTTON, padx=PADDING_BUTTON, pady=PADDING_BUTTON) self.exit_button.pack(ipadx=PADDING_BUTTON/3, ipady=PADDING_BUTTON, padx=PADDING_BUTTON, pady=PADDING_BUTTON)
self.exit_button.bind('<Button-1>', self.close) self.exit_button.bind('<Button-1>', self.close)
Style().configure("Menu.TButton", font=("Lucida", 25)) self.about_info = Label(self.master)
Style().configure("Quit.TButton", font=("Lucida", 15)) self.about_info.config(text="Game Created by TheOrangeOne!", font=("Courier New", 9))
self.about_info.bind("<Button-1>", self.show_site)
self.about_info.pack(side="top", padx=0, pady=PADDING_BUTTON/2)
Style().configure("Menu.TButton", font=("Lucida", 21))
Style().configure("About.TButton", font=("Lucida", 17))
Style().configure("Quit.TButton", font=("Lucida", 13))
self.options_window = Options_Window() self.options_window = Options_Window()
logging.debug("GUI Generated.") logging.debug("GUI Generated.")
@ -47,54 +63,77 @@ class Main_Window:
self.new_window = Toplevel(self.master) self.new_window = Toplevel(self.master)
self.options_window.display(self.new_window) self.options_window.display(self.new_window)
def show_info(self, event):
logging.info("Loading About Page...")
system("start https://bitbucket.org/theorangeone/attack-on-blocks/wiki/Home")
def close(self, event): def close(self, event):
logging.critical("Closing Main Window.") logging.critical("Closing Main Window.")
self.master.destroy() self.master.destroy()
def show_site(self, event):
logging.info("Loading Website")
system("start http://theorangeone.net")
class Options_Window: class Options_Window:
def __init__(self): def __init__(self):
self.textures_object = Textures() self.textures_object = Textures()
self.options = { self.options = {
"Difficulty": 120, "Difficulty": 120,
"Textures": self.textures_object "Textures": self.textures_object,
"Sounds": True
} }
def display(self, master): def display(self, master):
self.master = master self.master = master
self.master.title("SPACE INVADERS - Options") self.master.title("ATTACK ON BLOCKS - Options")
self.title = Label(self.master) self.title = Label(self.master)
self.title.config(text="OPTIONS",font=("Courier New", 37)) self.title.config(text="OPTIONS",font=("Courier New", 37))
self.title.pack(side="top", padx=PADDING_TITLE, pady=PADDING_TITLE/2) self.title.pack(side="top", padx=PADDING_TITLE, pady=PADDING_TITLE/2)
self.difficulty_title = Label(self.master) self.difficulty_title = Label(self.master)
self.difficulty_title.config(text="Current Difficulty: {}".format(self.options["Difficulty"]), font=("Courier New", 19)) self.difficulty_title.config(text="Current Difficulty: {}".format(self.options["Difficulty"]), font=("Courier New", 13))
self.difficulty_title.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON) self.difficulty_title.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON)
self.difficulty_scale = Scale(self.master, from_=30, to=300, orient="horizontal", command=self.update_difficulty, length=400) self.difficulty_scale = Scale(self.master, from_=5, to=500, orient="horizontal", command=self.update_difficulty, length=350)
self.difficulty_scale.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON/3) self.difficulty_scale.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON/3)
self.difficulty_scale["value"] = self.options["Difficulty"]
self.difficulty_reset_button = Button(self.master, style="Minor.TButton")
self.difficulty_reset_button.config(text="Reset Difficulty")
self.difficulty_reset_button.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON/3)
self.difficulty_reset_button.bind('<Button-1>', self.reset_difficulty)
Frame(self.master,height=23).pack()
self.texture_title = Label(self.master) self.texture_title = Label(self.master)
self.texture_title.config(text="Select Texture Pack", font=("Courier New", 19)) self.texture_title.config(text="Select Texture Pack", font=("Courier New", 13))
self.texture_title.pack(side="bottom", ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON) self.texture_title.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON)
self.texture_select = ListBox(master) self.texture_select = Listbox(master)
self.texture_select.delete(0, END)
for directory in self.options["Textures"].list_packs(): for directory in self.options["Textures"].list_packs():
if directory == "": continue
self.texture_select.insert(END, directory) self.texture_select.insert(END, directory)
self.texture_select.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON/3) self.texture_select.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON/3)
self.exit_button = Button(self.master, style="Minor.TButton") Frame(self.master,height=23).pack()
self.exit_button.config(text="Reset")
self.exit_button.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON/3) self.using_sounds = IntVar()
self.exit_button.bind('<Button-1>', self.reset_difficulty) self.using_sounds.set(self.options["Sounds"])
self.sounds_check = Checkbutton(self.master, text="Use Sound Effects", command=self.update_sounds, variable=self.using_sounds)
self.sounds_check.pack(ipadx=PADDING_BUTTON/3, padx=PADDING_BUTTON)
Style().configure("Minor.TButton", font=("Lucida", 10)) Style().configure("Minor.TButton", font=("Lucida", 10))
self.dlgWin.protocol('WM_DELETE_WINDOW', self.close) self.master.protocol('WM_DELETE_WINDOW', self.close)
logging.info("Options menu created.") logging.info("Options menu created.")
def close(self): def close(self):
self.options["Textures"].pack = self.texture_select.get(ACTIVE) # Because it has no changed event self.options["Textures"].pack = self.texture_select.get(ACTIVE) if self.texture_select.get(ACTIVE) != "" else "default" # Because it has no changed event
logging.info("Selected Texture Pack: {}".format(self.options["Textures"].pack))
self.master.destroy() self.master.destroy()
def update_sounds(self):
self.options["Sounds"] = self.using_sounds.get()
def update_difficulty(self, event): def update_difficulty(self, event):
self.options["Difficulty"] = int(self.difficulty_scale.get()) self.options["Difficulty"] = int(self.difficulty_scale.get())
self.difficulty_title["text"] = "Current Difficulty: {}".format(self.options["Difficulty"]) self.difficulty_title["text"] = "Current Difficulty: {}".format(self.options["Difficulty"])

22
LICENSE Normal file
View file

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Jake Howard
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,3 +1,3 @@
print("Starting Space Invaders...\nLoading Main Window...") print("Starting Attack on Blocks...\nLoading Main Window...")
import GUI import GUI
GUI.display() GUI.display()

View file

@ -1,24 +1,26 @@
# Space Invaders # # Attack on Blocks #
This take on space invaders was written for my IT BTEC course, Unit 21 Games Development at college. This version, written in python, includes more advanced features such as resource packs. This take on space invaders was written for my IT BTEC course, Unit 22 Games Development at college. This version, written in python, includes more advanced features such as resource packs.
### More Information ###
For more information, check out the [Wiki](//bitbucket.org/TheOrangeOne/attack-on-blocks/wiki) page.
### Requirements ### ### Requirements ###
* Python * Python 3
* Pygame * Pygame
* TKinter * TKinter
The game is only playable on windows, due to the GUI library only being available on windows. However a cross platform, lightweight version may be made in the future. The game is only playable on windows, due to the GUI library only being available on windows. However a cross platform, lightweight version may be made in the future.
### Playing the game ### ### Playing the game ###
* Clone the repository * Clone the repository, or visit the downloads page
* Install the required libraries (See Above) * Install the required libraries (See Above)
* Run 'Play The Game.py' * Run 'Play The Game.py'
### Core Contributors ### ### Core Contributors ###
* Jake Howard * Jake Howard
* Furhan Bhatti * Furhan Bhatti (Well not really)
# Note #
At the moment, the game WILL NOT play at all, as it is still in development, all the time this message is here, the program will not run!

BIN
Thumbs.db

Binary file not shown.

View file

@ -5,53 +5,66 @@ from random import randint
class Textures(): class Textures():
def __init__(self): def __init__(self):
self.images = { self.images = {
"PLAYER":"player.png", "PLAYER":"player",
"BULLET":"bullet.png", "BULLET":"bullet",
"TARGETS":[], "TARGETS":[],
"SHOOTER":"shooter.png", "SHOOTER":"shooter",
"TARGET_BULLET":"target_bullet.png" "TARGET_BULLET":"bullet_target",
"POWERUP": "powerup"
} }
self.path=os.path.dirname(os.path.realpath(__file__)) + "\\resources\\texture_packs\\" self.path=os.path.dirname(os.path.realpath(__file__)) + "\\resources\\texture_packs\\"
self.pack = "default" self.pack = "default"
def load_texture_pack(self, packName): def load_texture_pack(self, pack_name):
if os.path.exists(self.path + packName): if os.path.exists(self.path + pack_name):
self.images["TARGETS"] = [] self.images["TARGETS"] = []
targets = glob.glob(self.path+packName+"\\target*.png") targets = glob.glob(self.path+pack_name+"\\target*.png")
logging.debug("Found {0} target files.".format(len(targets))) logging.debug("Found {0} target files.".format(len(targets)))
for file in targets: for file in targets:
fileName = file.split("\\")[-1] filename = file.split("\\")[-1].replace(".png", "")
self.images["TARGETS"].append(filename) self.images["TARGETS"].append(filename)
self.pack = packName self.pack = pack_name
else: logging.warn("Cannot find texture pack '{}'".format(packName)) else: logging.warn("Cannot find texture pack '{}'".format(ppack_name))
def get_texture(self, objectName): def get_texture(self, objectName):
filename = self.path + self.pack + "\\{0}.png".format(self.images[objectName.upper()]) filename = self.path + self.pack + "\\{0}.png".format(self.images[objectName.upper()])
return pygame.image.load(filename) return pygame.image.load(filename)
def get_target_texture(self): def get_target_texture(self, ID=False):
filename = self.path + self.pack + "\\{}.png".format(self.images["TARGETS"][randint(0,len(self.images["TARGETS"]))]) if not ID:
return pygame.image.load(filename) index = randint(0,len(self.images["TARGETS"])-1) if len(self.images["TARGETS"]) >=1 else 0
filename = self.path + self.pack + "\\{}.png".format(self.images["TARGETS"][index])
return [pygame.image.load(filename), index]
else:
filename = self.path + self.pack + "\\target{}.png".format(int(ID))
return [pygame.image.load(filename), ID]
def list_packs(self): def list_packs(self):
return [x[0] for x in os.walk(self.path)] return [x[0].replace(self.path, "") for x in os.walk(self.path)]
Level_Template = namedtuple('Level_Template', ("rows", "padding", "firebacks", "powerups")) Level_Template = namedtuple('Level_Template', ("rows", "padding", "firebacks", "powerups"))
Levels = [ Levels = [
Level_Template(2, 20, 0, 0), Level_Template(2, 20, 0, 0),
Level_Template(3, 15, 1, 0),
Level_Template(4, 15, 3, 1),
Level_Template(3, 7, 2, 2),
Level_Template(5, 15, 2, 1),
Level_Template(2, 20, 100, 2), #All the enemies!
Level_Template(3, 15, 2, 1), Level_Template(3, 15, 2, 1),
Level_Template(4, 25, 7, 1) Level_Template(3, 7, 2, 4),
Level_Template(4, 15, 4, 3),
Level_Template(5, 35, 4, 6),
] ]
def generate_random_level(): def generate_random_level():
logging.info("Generating a random level!") logging.info("Generating a random level!")
rows = randint(0, 12) rows = randint(1, 12)
padding = randint(0, 30) padding = randint(5, 30)
firebacks = randint(0, 15) firebacks = randint(0, 15)
powerups = randint(0, 15) powerups = randint(0, 15)
return Level_Template(rows, padding, firebacks, powerups) return Level_Template(rows, padding, firebacks, powerups)
@ -59,9 +72,12 @@ def generate_random_level():
Sounds = {} Sounds = {}
def init_sounds(): def init_sounds():
music_files = ["main.mp3", "fire.mp3"] music_files = ["main.ogg", "OP.ogg", "shot.ogg"]
for file in music_files: for file in music_files:
path = os.path.dirname(os.path.realpath(__file__)) + "\\resources\\sounds\\" + file path = os.path.dirname(os.path.realpath(__file__)) + "\\resources\\sounds\\" + file
if file == "main.mp3": mixer = pygame.mixer.music.load(path) if file == "main.ogg":
else: mixer = pygame.mixer.Sound(file) mixer = pygame.mixer.music
Sounds.update(file.split(".")[0], mixer) mixer.load(path)
else: mixer = pygame.mixer.Sound(path)
mixer.set_volume(1.0)
Sounds[file.replace(".ogg", "")] = mixer

View file

@ -2,10 +2,10 @@ import pygame
class Bullet(pygame.sprite.Sprite): class Bullet(pygame.sprite.Sprite):
def __init__(self, parent): def __init__(self, parent, textures, bigger):
super().__init__() super().__init__()
self.width = 4 self.width = 6 * (1+int(bigger))
self.height = 10 self.height = 14 * (1+int(bigger))
self.image = pygame.transform.scale(textures.get_texture("BULLET"), (self.width, self.height)) self.image = pygame.transform.scale(textures.get_texture("BULLET"), (self.width, self.height))
self.rect = self.image.get_rect() self.rect = self.image.get_rect()
self.rect.x = parent.rect.x + parent.width/2 - self.width/2 self.rect.x = parent.rect.x + parent.width/2 - self.width/2

View file

@ -3,7 +3,7 @@ from time import sleep
def r9k(window): def r9k(window):
logging.warn("Look, you found a pepe!") logging.warn("Look, you found a pepe!")
raw_image = urllib.request.urlopen("https://38.media.tumblr.com/avatar_2cd47bc1ad07_128.png").read() raw_image = urllib.request.urlopen("http://img.ifcdn.com/images/620f230fad2806fe5305fac45dd673b8fc005b98c1e3b8584abc9c439b050950_1.jpg").read()
image_file = io.BytesIO(raw_image) image_file = io.BytesIO(raw_image)
image = pygame.transform.scale(pygame.image.load(image_file), window.get_size()) image = pygame.transform.scale(pygame.image.load(image_file), window.get_size())
window.blit(image, (0,0)) window.blit(image, (0,0))

157
game.py
View file

@ -5,36 +5,34 @@ import eggs
from bullet import Bullet from bullet import Bullet
from player import Shooter from player import Shooter
from assets import * from assets import *
from target import Target from target import Target, generate_targets
POWERUPS = ["SPEED", "DOUBLE", "LIVES", "SCORE", "BIGGER"]
PLAYING_GAME = False PLAYING_GAME = False
WINDOW_SIZE = (640,480) WINDOW_SIZE = (680, 790)
FPS = 120 HUD_COLOUR = (255,168,72)
def update_score(window, score): def update_score(window, score, colour=HUD_COLOUR):
font = pygame.font.SysFont(None, 30, bold=False) font = pygame.font.SysFont(None, 30, bold=False)
window.blit(font.render("Score: {}".format(int(score)), True, (255,0,0)), (25, WINDOW_SIZE[1] - 30)) window.blit(font.render("Score: {}".format(int(score)), True, colour), (25, WINDOW_SIZE[1] - 30))
def update_level(window, level): def update_level(window, level, colour=HUD_COLOUR):
font = pygame.font.SysFont(None, 25, bold=True)
window.blit(font.render("Level: {}".format(int(level)+1), True, (0,255,0)), (8.7*WINDOW_SIZE[0]/10, WINDOW_SIZE[1] - 30))
def update_lives(window, lives):
font = pygame.font.SysFont(None, 30, bold=False) font = pygame.font.SysFont(None, 30, bold=False)
window.blit(font.render("Lives Remaining: {}".format(int(lives)), True, (0,0,255)), (4.5*WINDOW_SIZE[0]/10, WINDOW_SIZE[1] - 30)) window.blit(font.render("Level: {}".format(int(level)+1), True, colour), (8.5*WINDOW_SIZE[0]/10, WINDOW_SIZE[1] - 30))
def update_lives(window, lives, colour=HUD_COLOUR):
font = pygame.font.SysFont(None, 30, bold=False)
window.blit(font.render("Lives Remaining: {}".format(int(lives)), True, colour if lives != 1 else (255,50,0)), (3.8*WINDOW_SIZE[0]/10, WINDOW_SIZE[1] - 30))
def initialise(menu, options): def initialise(menu, options):
pygame.mixer.pre_init(44100, -16, 2, 2048) pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.init() pygame.init()
init_sounds()
options["Difficulty"] = FPS
window = pygame.display.set_mode(WINDOW_SIZE) window = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption("Attack on Blocks")
exit_code = play(window, options) # Run main game loop exit_code = play(window, options) # Run main game loop
for key, value in Sounds.items(): for key, value in Sounds.items():
value.stop() value.fadeout(500)
logging.debug("Game Exited with code {}".format(exit_code)) logging.debug("Game Exited with code {}".format(exit_code))
if exit_code != "QUIT": sleep(1) if exit_code != "QUIT": sleep(1)
@ -43,77 +41,50 @@ def initialise(menu, options):
menu.deiconify() menu.deiconify()
return exit_code return exit_code
def generate_targets(player):
sprite_list = []
group = pygame.sprite.Group()
if player.level > len(Levels)-1:
level = generate_random_level()
else: level = Levels[player.level]
logging.debug("Generating Level: " + str(level))
for i in range(level.rows):
i *= level.padding + 8
for j in range(40, WINDOW_SIZE[0] - 40, level.padding + 8):
temp = Target(x=j,y=i, player.options["Textures"])
sprite_list.append(temp)
del temp
for i in range(level.firebacks):
changed = False
while not changed:
index = randint(0, len(sprite_list)-1)
if sprite_list[index].type != "SHOOTER":
sprite_list[index].type = "SHOOTER"
sprite_list[index].image = pygame.transform.scale(player.options["Textures"].get_texture("SHOOTER"), (sprite_list[index].width, sprite_list[index].height))
x,y = sprite_list[index].rect.x, sprite_list[index].rect.y
sprite_list[index].rect = sprite_list[index].image.get_rect()
sprite_list[index].set_position(x,y, center=False) #Already Centered!
changed = True
for sprite in sprite_list: #Because sprite groups dont support indexing!
group.add(sprite)
return group
def play(window, options): def play(window, options):
window_rect = window.get_rect() window_rect = window.get_rect()
options["Textures"].load_texture_pack(options["Textures"].pack)
player = Shooter(window=window) player = Shooter(window=window, texture=options["Textures"])
player.set_position(WINDOW_SIZE[0]/2, WINDOW_SIZE[1]*0.83) player.set_position(WINDOW_SIZE[0]/2, WINDOW_SIZE[1]*0.90)
player.options = options player.options = options
player_group = pygame.sprite.Group() player_group = pygame.sprite.Group()
player_group.add(player) player_group.add(player)
target_group = generate_targets(player) target_group = generate_targets(player, WINDOW_SIZE, Levels)
bullet_group = pygame.sprite.Group() bullet_group = pygame.sprite.Group()
clock = pygame.time.Clock() clock = pygame.time.Clock()
FPS = player.options["Difficulty"]
timeouts = { timeouts = {
"Target Movement":[FPS*0.5,FPS*0.5], "Target Movement":[FPS*0.65,FPS*0.65],
"Powerup":[FPS*100, FPS*100] "Powerup":[FPS*15, FPS*15]
} }
Sounds["main"].play(loops=-1) #Start background music init_sounds()
if options["Sounds"]: Sounds["main"].play(loops=-1) #Start background music
logging.info("Game Started.") logging.info("Game Started.")
PLAYING_GAME = True PLAYING_GAME = True
while PLAYING_GAME: while PLAYING_GAME:
window.fill((0,0,0)) window.fill((0,0,0))
fired = False
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
logging.critical("Exiting Game...") logging.critical("Exiting Game...")
PLAYING_GAME = False PLAYING_GAME = False
return "QUIT" return "QUIT"
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: if event.type == pygame.KEYDOWN and event.key in [pygame.K_SPACE, pygame.K_w, pygame.K_UP] and not fired:
temp = Bullet(player) if player.options["Sounds"]: Sounds["shot"].play()
temp = Bullet(player, player.options["Textures"], player.powerup == "BIGGER")
bullet_group.add(temp) bullet_group.add(temp)
if player.powerup == "DOUBLE":
temp = Bullet(player, player.options["Textures"], player.powerup == "BIGGER")
temp.rect.y += 20
bullet_group.add(temp)
fired = True
if event.type == pygame.KEYDOWN and event.key == pygame.K_KP_PLUS:
player.OP = not player.OP
logging.info("Player is now OP!")
keys = pygame.key.get_pressed() keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] or keys[pygame.K_d]: if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
@ -125,12 +96,28 @@ def play(window, options):
else: player.move(-player.speed) else: player.move(-player.speed)
if keys[pygame.K_KP4] and keys[pygame.K_KP5] and keys[pygame.K_KP6] and player.OP: if keys[pygame.K_KP4] and keys[pygame.K_KP5] and keys[pygame.K_KP6] and player.OP:
temp = Bullet(player) temp = Bullet(player, player.options["Textures"], False)
bullet_group.add(temp) bullet_group.add(temp)
if keys[pygame.K_r] and [pygame.K_9] and [pygame.K_k] and player.OP: if keys[pygame.K_r] and [pygame.K_9] and [pygame.K_k] and player.OP:
eggs.r9k(window) eggs.r9k(window)
if keys[pygame.K_KP4] and keys[pygame.K_KP2] and keys[pygame.K_KP0] and keys[pygame.K_o] and keys[pygame.K_p] and not player.OP:
if player.options["Sounds"]:
Sounds["main"].stop()
Sounds["OP"].play(loops=-1)
player.OP = True
player.change_colour((255,96,0))
logging.warn("OP mode engaged.")
if keys[pygame.K_KP_MINUS] and player.OP:
if player.options["Sounds"]:
Sounds["OP"].stop()
Sounds["main"].play(loops=-1)
player.OP = False
player.reset_image()
logging.warn("OP mode disabled.")
for sprite in bullet_group: for sprite in bullet_group:
sprite.update() sprite.update()
if sprite.rect.y < 0 or (sprite.rect.y > player.rect.y and sprite.type == "TARGET"): if sprite.rect.y < 0 or (sprite.rect.y > player.rect.y and sprite.type == "TARGET"):
@ -140,16 +127,21 @@ def play(window, options):
hit_list = pygame.sprite.spritecollide(bullet, target_group, False) hit_list = pygame.sprite.spritecollide(bullet, target_group, False)
for target in hit_list: for target in hit_list:
if bullet.type != "TARGET": if bullet.type != "TARGET":
target.lives -= 1
if target.lives <= 0:
target_group.remove(target) target_group.remove(target)
bullet_group.remove(bullet)
player.score += 1 player.score += 1
bullet_group.remove(bullet)
if target.lives <= 0 and target.type == "POWERUP":
player.powerup = POWERUPS[randint(0,len(POWERUPS)-1)]
logging.info("Powerup set to {}".format(player.powerup))
hit_list = pygame.sprite.spritecollide(bullet, player_group, False) hit_list = pygame.sprite.spritecollide(bullet, player_group, False)
for player in hit_list: for player in hit_list:
if bullet.type == "TARGET": if bullet.type == "TARGET":
bullet_group.remove(bullet) bullet_group.remove(bullet)
logging.info("You were hit by a target's bullet!") logging.info("You were hit by a target's bullet!")
player.lives -= 1 if not player.OP: player.lives -= 1
if player.lives <= 0: if player.lives <= 0:
return "LIVES" return "LIVES"
@ -157,10 +149,10 @@ def play(window, options):
drop_targets = False drop_targets = False
for target in target_group: for target in target_group:
target.move() target.move()
if target.rect.x <= 30 or target.rect.x >=WINDOW_SIZE[0] - 30: if target.rect.x <= 30 or target.rect.x >=WINDOW_SIZE[0] - target.width/2 - 30:
drop_targets = True drop_targets = True
if target.rect.y >= player.rect.y + 20: if target.rect.y >= player.rect.y + target.height/2:
PLAYING_GAME = False PLAYING_GAME = False
return "PLAYER COLLISION" return "PLAYER COLLISION"
@ -171,35 +163,44 @@ def play(window, options):
timeouts["Target Movement"][0] = timeouts["Target Movement"][1] timeouts["Target Movement"][0] = timeouts["Target Movement"][1]
if timeouts["Powerup"][0] <= 0:
timeouts["Powerup"][0] = timeouts["Powerup"][1]
if player.powerup == "SCORE":
player.score += 10
player.powerup = ""
elif player.powerup == "LIVES":
player.lives += 1
player.powerup = ""
for target in target_group: for target in target_group:
if target.type == "SHOOTER": if target.type == "SHOOTER":
if randint(0,375) > 1: continue if randint(0,600) > 1: continue
temp = Bullet(target) temp = Bullet(target, player.options["Textures"], False)
temp.type="TARGET" temp.type="TARGET"
temp.image = pygame.transform.scale(textures.get_texture("TARGET_BULLET"), (temp.width, temp.height)) temp.image = pygame.transform.scale(player.options["Textures"].get_texture("TARGET_BULLET"), (temp.width, temp.height))
x,y = temp.rect.x, temp.rect.y x,y = temp.rect.x, temp.rect.y
temp.rect = temp.image.get_rect() temp.rect = temp.image.get_rect()
temp.set_position(x,y) temp.set_position(x,y)
temp.speed = -3 #So it shoots down! temp.speed = -1 #So it shoots down!
bullet_group.add(temp) bullet_group.add(temp)
if len(target_group) == 0: #If all current players are gone. if len(target_group) == 0: #If all current players are gone.
player.level += 1 player.level += 1
target_group = generate_targets(player) Sounds["main"].set_volume(0.5)
player.change_colour(player.colours[player.level]) target_group = generate_targets(player, WINDOW_SIZE, Levels)
target_group.draw() target_group.draw(window)
bullet_group.empty()
pygame.display.update() pygame.display.update()
sleep(1.5) sleep(0.75)
Sounds["main"].set_volume(1.0)
if player.OP:
player.change_colour((255,96,0)) #override colour change if changed before
update_score(window, player.score) update_score(window, player.score)
update_level(window, player.level) update_level(window, player.level)
update_lives(window, player.lives) update_lives(window, player.lives)
bullet_group.draw(window)
target_group.draw(window) target_group.draw(window)
bullet_group.draw(window)
player_group.draw(window) player_group.draw(window)
for key, value in timeouts.items(): for key, value in timeouts.items():

View file

@ -2,12 +2,13 @@ import pygame
class Shooter(pygame.sprite.Sprite): class Shooter(pygame.sprite.Sprite):
def __init__(self, window, texture, colour=(255,255,255), width=45, height=20): def __init__(self, window, texture, colour=(255,255,255), width=55, height=25):
super().__init__() super().__init__()
self.width = width self.width = width
self.height = height self.height = height
self.colour = colour self.colour = colour
self.image = pygame.transform.scale(textures.get_texture("PLAYER"), (self.width, self.height)) self.texture = texture
self.image = pygame.transform.scale(self.texture.get_texture("PLAYER"), (self.width, self.height))
self.rect = self.image.get_rect() self.rect = self.image.get_rect()
self.speed = 3 self.speed = 3
self.window_rect = window.get_rect() self.window_rect = window.get_rect()
@ -17,7 +18,6 @@ class Shooter(pygame.sprite.Sprite):
self.level = 0 self.level = 0
self.lives = 3 self.lives = 3
self.powerup = "" self.powerup = ""
self.colours = [(255,0,0), (255,255,0), (0,255,0)]
def set_position(self,x,y): def set_position(self,x,y):
self.rect.x, self.rect.y = x, y self.rect.x, self.rect.y = x, y
@ -35,3 +35,9 @@ class Shooter(pygame.sprite.Sprite):
self.image.fill(colour) self.image.fill(colour)
self.rect = self.image.get_rect() self.rect = self.image.get_rect()
self.set_position(x,y) self.set_position(x,y)
def reset_image(self):
x,y = self.rect.x, self.rect.y
self.image = pygame.transform.scale(self.texture.get_texture("PLAYER"), (self.width, self.height))
self.rect = self.image.get_rect()
self.set_position(x,y)

BIN
resources/sounds/OP.ogg Normal file

Binary file not shown.

BIN
resources/sounds/main.ogg Normal file

Binary file not shown.

BIN
resources/sounds/shot.ogg Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View file

@ -1,23 +1,27 @@
import pygame import pygame, logging
from random import randint from random import randint
from game import generate_random_level
class Target(pygame.sprite.Sprite): class Target(pygame.sprite.Sprite):
def __init__(self, x, y, textures, color=(30,0,150), width=16, height=16): def __init__(self, x, y, textures, color=(30,0,150), width=23, height=23):
super().__init__() super().__init__()
self.width = width self.width = width
self.height = height self.height = height
self.image = pygame.transform.scale(textures.get_target_texture(), (self.width, self.height)) self.textures = textures
self.default_texture = textures.get_target_texture()
self.image = pygame.transform.scale(self.default_texture[0], (self.width, self.height))
self.rect = self.image.get_rect() self.rect = self.image.get_rect()
self.speed = 7 self.speed = 5
self.rect.x, self.rect.y = (x+(self.width/2)),(y+(self.width/2)) # centres co-ordinates self.rect.x, self.rect.y = (x+(self.width/2)),(y+(self.width/2)) # centres co-ordinates
self.type = "NORMAL" self.type = "NORMAL"
self.lives = 1
def move(self): def move(self):
self.rect.x += self.speed self.rect.x += self.speed
def drop(self): def drop(self):
self.rect.y += 17 self.rect.y += 13
self.speed *= -1 self.speed *= -1
def set_position(self, x, y, center=False): def set_position(self, x, y, center=False):
@ -26,4 +30,56 @@ class Target(pygame.sprite.Sprite):
else: else:
self.rect.x, self.rect.y = x, y self.rect.x, self.rect.y = x, y
def generate_targets(player, window_size, Levels):
sprite_list = []
group = pygame.sprite.Group()
if player.level > len(Levels)-1:
level = generate_random_level()
else: level = Levels[player.level]
logging.debug("Generating Level: " + str(level))
for i in range(level.rows):
i *= level.padding + 8
for j in range(75, window_size[0] - 75, level.padding + 10):
temp = Target(x=j,y=i, textures=player.options["Textures"])
sprite_list.append(temp)
del temp
if len(sprite_list) < level.firebacks:
firebacks = len(sprite_list)
else: firebacks = level.firebacks
for i in range(firebacks):
loop = 0
changed = False
while not changed:
if loop == firebacks: changed = True
index = randint(0, len(sprite_list)-1) if (len(sprite_list) - 1 != 0) else 0
if sprite_list[index].type != "SHOOTER":
sprite_list[index].type = "SHOOTER"
sprite_list[index].lives = 2
sprite_list[index].image = pygame.transform.scale(player.options["Textures"].get_texture("SHOOTER"), (sprite_list[index].width, sprite_list[index].height))
x,y = sprite_list[index].rect.x, sprite_list[index].rect.y
sprite_list[index].rect = sprite_list[index].image.get_rect()
sprite_list[index].set_position(x,y, center=False) #Already Centered!
changed = True
loop += 1
if len(sprite_list) < level.powerups:
powerups = len(sprite_list)
else: powerups = level.powerups
for i in range(powerups):
changed = False
while not changed:
index = randint(0, len(sprite_list)-1) if (len(sprite_list) - 1 != 0) else 0
if sprite_list[index].type != "POWERUP" and sprite_list[index].type != "SHOOTER" :
sprite_list[index].type = "POWERUP"
sprite_list[index].image = pygame.transform.scale(player.options["Textures"].get_texture("POWERUP"), (sprite_list[index].width, sprite_list[index].height))
x,y = sprite_list[index].rect.x, sprite_list[index].rect.y
sprite_list[index].rect = sprite_list[index].image.get_rect()
sprite_list[index].set_position(x,y, center=False) #Already Centered!
changed = True
for sprite in sprite_list: #Because sprite groups dont support indexing!
group.add(sprite)
return group