当前位置:网站首页>Pgzero aircraft war
Pgzero aircraft war
2022-07-29 02:51:00 【CairBin】
Pgzero Aircraft battle
Tips
About Pgzero For more basic things, please refer to my previous article
utilize pgzero Play a little game of catching the ball - Colorful world CairBin’s Blog
problem
Problem solved & characteristic :
In this project, I wrote it myself gameObject Base class replaced pgzero Medium Actor class , And all objects in the project inherit this class
The reason for this is , Because I found out Actor Unable to zoom the picture , I use pygame.transform.scale That solved the problem
Questions to be considered :
- The most incomprehensible part of this project is the precise collision . Originally, I wanted to pass pygame Of mask.overlap To achieve precise collision , But no matter how I change it offset The vertical and horizontal coordinates of the coordinate difference tuple are 0, If there is any way, please let me know in the article or in a private letter
- I judge the overlap of two rectangles according to coordinates to realize collision detection , But the white space around the picture will also trigger , Therefore, this method is not an accurate detection
- There is no explosion effect when the enemy explodes , The reason is that I forgot to write (doge). It's also easy to implement , My idea is to change it into an explosion picture when it explodes , It is best to gif type ( I don't like it pgzero Built in animation class , It feels strange to use ), Then the effect disappears after a certain time
Code
resources
Resources come from the Internet ( Non commercial use ), I pack and upload to Baidu cloud 、CSDN Resources , Or directly from GitHub Get on the
Baidu cloud Extraction code :6d1r
CSDN resources Points are required , If you want to “ sponsorship ” The author , You can download in this way (doge)
define.py
file define.py Some constants are defined ( Not a real constant ), Easy to maintain code
# Window parameters
WINDOW_TITLE = 'plane war'
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 500
BG_COLOR = 'white'
# Block size Long / wide
BLOCK_SIZE = 50
# Aircraft HP
PLANE_HP = 3
# Bullet parameters
BULLET_SPEED = 10
BULLET_SIZE = (10, 10)
BULLET_MOVE_LENGTH = -20
BULLET_AGRES = 1
# Enemy parameters
ENEMY_SPEEED = 5
ENEMY_CREATE_TIME = 30
# Blood volume
HEART_SIZE = 30
gameObject.py
file gameObject.py Used to create common properties and methods that all objects have ( Parent class )
from typing import Tuple
from numpy import rec
import pygame
from enum import Enum
# Coordinate anchor
class posAnchor(Enum):
TOP_LEFT = 0 # upper left
TOP = 1 # Just above
TOP_RIGHT = 2 # upper right
LEFT = 3 # Left
CENTER = 4 # center
RIGHT = 5 # Right
BOTTOM_LEFT = 6 # lower left
BOTTOM = 7 # Directly below
BOTTOM_RIGHT = 8 # Lower right
# Game base class
class gameObject:
def __init__(self, img, init_pos:tuple, size:tuple, screen = None, pos_anchor=posAnchor.TOP_LEFT) -> None:
self.img = img # pgzero Image objects
self.size = size # size , Tuples ( wide , high )
self.screen = screen # screen
self.destroy = False # Used to detect whether it is destroyed ,spiritGroup Medium checkDestroy Method to detect this property , by True Will be taken from spiritGroup Be removed in the
self.__anchor = pos_anchor # anchor
self.__pos = self.__getTruePos(init_pos, self.__anchor) # Draw coordinates
self.__userPos = init_pos # Anchor coordinates
# Picture container object , Need to import pygame
self.obj = pygame.transform.scale(self.img, self.size)
# initialization , stay pgzero update() Call in
def update(self, screen):
self.initScreen(screen)
self.draw()
# initialization screen
def initScreen(self, screen):
self.screen = screen
# draw
def draw(self):
self.screen.blit(self.obj, self.__pos)
# modify location ( Anchor point required , Prevent coordinate confusion )
def changePos(self, pos: tuple, pos_anchor):
self.__pos = self.__getTruePos(pos, pos_anchor)
self.__userPos = pos
# Get the width
def width(self):
return self.size[0]
# Get height
def height(self):
return self.size[1]
# Get size
def getSize(self):
return self.size
# Get abscissa ( Anchor coordinates )
def x(self):
return self.__userPos[0]
# Get ordinate ( Anchor coordinates )
def y(self):
return self.__userPos[1]
# Get the coordinates of the upper left corner
def getTopLeftPos(self):
return self.__pos
# obtain rect
def getRect(self):
return self.obj.get_rect()
# obtain mask
def getMask(self):
return pygame.mask.from_surface(self.obj)
# Get anchors
def getAnchor(self):
return self.__anchor
# Change the destroy attribute
def setDestroy(self, choose:bool):
self.destroy = choose
# Get destroy attribute
def getDestroy(self)->bool:
return self.destroy
# collision detection
def collisionDetection(self, other):
this_pos = self.getTopLeftPos()
other_pos = other.getTopLeftPos()
this_center_pos = (this_pos[0]+self.width()/2, this_pos[1]+self.height()/2)
other_center_pos = (other_pos[0]+other.width()/2, other_pos[1]+other.height()/2)
# Determine the intersection of rectangles
if abs(this_center_pos[0] - other_center_pos[0]) <= (self.width() + other.width())/2 and abs(this_center_pos[1] - other_center_pos[1]) <= (self.height() + other.height())/2:
return True
else:
return False
def move(*args):
pass
# Give the coordinates according to the anchor and , Get the coordinates of the upper left corner
def __getTruePos(self, pos: tuple, pos_anchor):
if pos_anchor == posAnchor.TOP_LEFT:
return pos
elif pos_anchor == posAnchor.TOP:
return (pos[0]-self.size[0]/2, pos[1])
elif pos_anchor == posAnchor.TOP_LEFT:
return (pos[0]-self.size[0], pos[1])
elif pos_anchor == posAnchor.LEFT:
return (pos[0], pos[1]-self.size[1]/2)
elif pos_anchor == posAnchor.CENTER:
return (pos[0]-self.size[0]/2, pos[1]-self.size[1]/2)
elif pos_anchor == posAnchor.RIGHT:
return (pos[0]-self.size[0], pos[1]-self.size[1]/2)
elif pos_anchor == posAnchor.BOTTOM_LEFT:
return (pos[0], pos[1]-self.size[1])
elif pos_anchor == posAnchor.BOTTOM:
return (pos[0]-self.size[0]/2, pos[1]-self.size[1])
elif pos_anchor == posAnchor.BOTTOM_RIGHT:
return (pos[0]-self.size[0], pos[1]-self.size[1])
else:
return None
# Spirit group
class spiritGroup:
def __init__(self) -> None:
self.__spiritList = []
# ---------------------- The list of operations
# Additional
def append(self, spirit: gameObject):
self.__spiritList.append(spirit)
# Indexes
def index(self, g_obj: gameObject):
return self.__spiritList.index(g_obj)
# Insert
def insert(self, num):
self.__spiritList.insert(num)
# remove
def remove(self, g_obj: gameObject):
self.__spiritList.remove(g_obj)
# Remove by index
def removeAsIndex(self, num):
self.remove(self.index(num))
# Element number
def size(self):
return len(self.__spiritList)
# Empty
def clear(self):
self.__spiritList.clear()
# ---------------------- Operator overloading
# []
def __getitem__(self, index) -> gameObject:
return self.__spiritList[index]
# in
def __contains__(self, elem):
return
# +
def __add__(self, other):
new_g_obj = spiritGroup()
for i in self.__spiritList:
new_g_obj.append(i)
for i in other:
new_g_obj.append(i)
return new_g_obj
# ---------------------- Basic operation
# initialization (draw)
def update(self, screen):
for i in self.__spiritList:
i.update(screen)
# draw
def draw(self):
for i in self.__spiritList:
i.draw()
# collision detection
def collisionDetection(self, other, collided = None, args=()):
for e in self.__spiritList:
for i in other:
if e.collisionDetection(i) == True:
if collided == None:
e.setDestroy(True)
i.setDestroy(True)
else:
collided(e, i, *args)
# Move
def move(self, *args):
for i in self.__spiritList:
i.move(*args)
# Detect whether the element should be destroyed ( remove ), And implement
def checkDestroy(self):
for i in self.__spiritList:
if i.getDestroy():
temp = i
self.remove(i)
del i
actors.py
file actors.py Define the class of the specific creation object in the game , For example, aircraft , Bullets, etc
import define
import gameObject
# Bullets
class bullet(gameObject.gameObject):
def __init__(self, img, init_pos: tuple, size: tuple, screen=None, pos_anchor=...) -> None:
super().__init__(img, init_pos, size, screen, pos_anchor)
self.speed = define.BULLET_MOVE_LENGTH
self.agres = define.BULLET_AGRES # Bullet power
def move(self, *args):
self.changePos((self.x(), self.y()+self.speed), self.getAnchor())
pos = self.getTopLeftPos()
if pos[1]+self.height() < 0:
self.setDestroy(True)
# Aircraft
class plane(gameObject.gameObject):
def __init__(self, img, init_pos: tuple, size: tuple, screen=None, pos_anchor=...) -> None:
super().__init__(img, init_pos, size, screen, pos_anchor)
self.hp = define.PLANE_HP # Player aircraft HP
def move(self, *args):
# Boundary judgment
pos = list((args[0][0]-self.width()/2, args[0][1]-self.height()/2))
if pos[0] <0:
pos[0] = 0
if pos[0]+self.width() > define.WINDOW_WIDTH:
pos[0] = define.WINDOW_WIDTH-self.width()
if pos[1]<0:
pos[1] = 0
if pos[1]+self.height() > define.WINDOW_HEIGHT:
pos[1] = define.WINDOW_HEIGHT-self.height()
self.changePos(tuple(pos), gameObject.posAnchor.TOP_LEFT)
# FireStarter , The parameter is bullet pgzero Image objects
def fire(self, bullet_img):
pos = self.getTopLeftPos()
bullet_pos = (pos[0]+self.width()/2, pos[1])
bull = bullet(bullet_img, bullet_pos, define.BULLET_SIZE, screen = self.screen, pos_anchor=gameObject.posAnchor.BOTTOM)
return bull
# Enemy human
class enemy(gameObject.gameObject):
def __init__(self, img, hp, init_pos: tuple, size: tuple, screen=None, pos_anchor=...) -> None:
super().__init__(img, init_pos, size, screen, pos_anchor)
self.hp = hp
self.speed = define.ENEMY_SPEEED
self.destroy = False
def move(self, *args):
if self.destroy == False:
self.changePos((self.x(), self.y()+self.speed),
gameObject.posAnchor.CENTER)
pos = self.getTopLeftPos()
if pos[1] > define.WINDOW_HEIGHT:
self.setDestroy(True)
# Blood volume class , Used for display hp
class heart(gameObject.gameObject):
def __init__(self, img, init_pos: tuple, size: tuple, screen=None, pos_anchor=...) -> None:
super().__init__(img, init_pos, size, screen, pos_anchor)
main.py
main.py The main entry of the program is in this file
import random
import pgzrun
import define
import actors
import pygame, sys
# Basic window configuration , pgzero The variables here will be called to set the window
TITLE = define.WINDOW_TITLE
WIDTH = define.WINDOW_WIDTH
HEIGHT = define.WINDOW_HEIGHT
# Picture mapping dictionary
images_dict = {
'plane': images.plane,
'bullet': images.bullet,
'enemy': images.enemy,
'heart': images.heart
}
# Bullet group
bullet_list = actors.gameObject.spiritGroup()
# Enemy group
enemy_list = actors.gameObject.spiritGroup()
# Blood volume display group
heart_list = actors.gameObject.spiritGroup()
# Character plane
plane = actors.plane(images_dict['plane'], (define.WINDOW_WIDTH/2, define.WINDOW_HEIGHT*3/4),
(define.BLOCK_SIZE, define.BLOCK_SIZE), pos_anchor=actors.gameObject.posAnchor.CENTER)
# Generate enemy interval
enemy_time = 0
# Game score
player_scores = 0
# ------------------------------------------------- Game control ----------------------------------- #
# Randomly generate enemies
def creatEnemy():
global enemy_time
if enemy_time <= 0:
# The blood volume here is random 1-2
enemy_list.append(actors.enemy(images_dict['enemy'], random.randint(1,2),
(random.randint(5, define.WINDOW_WIDTH-define.BLOCK_SIZE), 0), (define.BLOCK_SIZE, define.BLOCK_SIZE),
pos_anchor=actors.gameObject.posAnchor.TOP_LEFT))
enemy_time = define.ENEMY_CREATE_TIME
else:
enemy_time -= 1
# Display blood volume
def showHp():
hp = plane.hp
i = 0
heart_list.clear()
while i<hp:
he = actors.heart(images_dict['heart'], (i*define.HEART_SIZE, 0), (define.HEART_SIZE,
define.HEART_SIZE), pos_anchor=actors.gameObject.posAnchor.TOP_LEFT)
heart_list.append(he)
i+=1
# score
def getScores():
global player_scores
player_scores += 1
# Game over
def gameOver():
global player_scores
pygame.quit()
print('Game Over')
print('Your scores are {}'.format(player_scores))
sys.exit()
# Callback function of bullets colliding with enemy aircraft
# The default collision detection directly deletes objects , If you set the amount of blood for the enemy to deduct blood according to the power of the bullet, you need to provide an external callback function
def bulletCollidedEnemy(bullet: actors.bullet, enemy: actors.enemy, getScore):
enemy.hp -= bullet.agres
bullet.setDestroy(True) # Destroy bullets
# Judge whether the enemy is destroyed according to the amount of blood
if enemy.hp <= 0:
enemy.setDestroy(True)
getScore() # score
# Enemy planes collide with players
# There is no spirit group in the player plane , So write the collision event directly in Update() Call in
def enemyCollidedPlane():
# Traverse and detect collisions
for i in enemy_list:
if i.collisionDetection(plane):
plane.hp -= 1 # Blood deduction
i.setDestroy(True)
# Check whether the blood volume returns to zero to end the game
if plane.hp == 0:
gameOver()
# -------------------------------------------------pgzero built-in ----------------------------------- #
def update():
plane.update(screen)
bullet_list.update(screen)
bullet_list.move()
creatEnemy()
enemy_list.update(screen)
enemy_list.move()
enemy_list.checkDestroy()
showHp()
heart_list.update(screen)
bullet_list.collisionDetection(enemy_list, collided=bulletCollidedEnemy, args=(getScores,))
bullet_list.checkDestroy()
enemyCollidedPlane()
def draw():
screen.fill(define.BG_COLOR)
plane.draw()
bullet_list.draw()
enemy_list.draw()
heart_list.draw()
def on_mouse_move(pos):
plane.move(pos)
def on_key_down(key):
# The space plane fired bullets
if key == keys.SPACE:
bullet_list.append(plane.fire(images_dict['bullet']))
# ------------------------------------------------- function -----------------------------------#
pgzrun.go()
Open source
Github:
边栏推荐
- Rocbos open source micro community light forum source code
- C language: judging letters
- 工科男生:20岁未满,平凡但不平庸
- Introduction to network foundation
- laravel框架中实现封装公共方法全局调用
- owt-server源码剖析(三)--video模块分析之Mixer In
- K210 - sound source location and sound recognition
- UE4.25 Slate源码解读
- 架构师进阶,微服务设计与治理的 16 条常用原则
- 一款好看的iapp捐赠榜单源码
猜你喜欢

Flink生产环境经典问题汇总

Source code of Jiugongge heart puzzle Applet / source code of main wechat applet with traffic

Notes on the sixth day

Some new ideas about time complexity

【OpenCV】使用OpenCV调用手机摄像头

Cloud development pocket toolbox wechat applet source code

etcd实现大规模服务治理应用实战

New UI Sifang aggregate payment system source code / new usdt withdrawal / latest update security upgrade to fix XSS vulnerability patch vulnerability

【报错】node:internal/modules/cjs/loader:936 【解决方法】

云开发打工人必备上班摸鱼划水微信小程序源码
随机推荐
MySQL - count(字段)、count(主键)、count(1)、count(*)的区别
Pgzero飞机大战
R语言ERROR: compilation failed for package ‘****‘
多重继承与派生类成员标识
FTP protocol details
Library management system
C language: judging letters
xxxxx
践踏---离散化+树状数组+差分
解析机器人与人类情感共鸣的主观意识
owt-server源码剖析(四)--video模块分析之Mixer Out
Source code of Jiugongge heart puzzle Applet / source code of main wechat applet with traffic
Family relationship calculator wechat applet source code
全新UI四方聚合支付系统源码/新增USDT提现/最新更新安全升级修复XSS漏洞补单漏洞
Deliver temperature with science and technology, vivo appears at the digital China Construction Summit
Notes on the seventh day
Multimodal unsupervised image to image translation
h. 264 code stream explanation
STP protocol (spanning tree protocol)
混淆矩阵学习笔记