猫史档案馆


【pygame:喵大战】教你用pygame开发游戏 Season3 Part1

用户:天上的流星_tianqiVirus天上的流星_tianqiVirus查看:1 回复:3 评论:1 创建时间:2019-12-29T13:34:29


教你用pygame开发游戏

今日游戏:喵大战(自创)

如果对几行代码没有看懂,那么你可能是没看过上一次的帖子

那就去看看我之前的帖子

 

前几周我的电脑碎了,现在终于弄好过来

为了庆祝,我决定开发一个游戏

我们先来弄点图片

center_imagecenter_image

暂时就这两张,分别命名为myTank.pngenemyTank.png

保存于py文件所属文件夹下assests/image文件夹

然后就是写代码了

做成大概这个样子

如果你看不懂代码,请参考我以前的帖子

import pygame

width = 720
height = 540
fps = 32
title = 'tank war'

pygame.init()
screen = pygame.display.set_mode([width,height])
pygame.display.set_caption(title)
timer = pygame.time.Clock()

keepGoing = True
doingTime = 0

while keepGoing:
	doingTime+=1
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			keepGoing = False

	pygame.display.update()
	timer.tick(32)

exit()

这里我先讲一下一些代码

pygame.display.set_caption()是设置标题

使用doingTime变量是为了方便在主循环中计数

然后准备图片文件center_image

ok

下一步,我们开始面向对象的编程

在主循环钱编写玩家喵的代码

先搭基本框架

class player:
	def __init__(self,x,y,image):
		pass
	def playerUpdate(self,screen):
		pass

在此,我们喵家显示和更新的代码放在一个方法里

然后,我们进行初始化玩家的操作

	def __init__(self,x,y,image):
		self.x = x
		self.y = y
		self.speed = 3
		self.image = image
		self.rect = pygame.Rect(self.x+4,self.y+12,10,12)

在这里我要指出,可以使用get_rect()的方法创建rect对象,但是这样会导致把过多的空余部分算进去

所以我还是用普通的pygame.Rect创建

然后我们编写玩家更新的代码

	def playerUpdate(self,screen):
		self.rect = pygame.Rect(self.x+4,self.y+12,10,12)
		screen.blit(self.image,(self.x,self.y))

请注意,这里的screen和上面的screen = pygame.display.set_mode()screen不一样

前者是playerUpdate传入的参数

好的,现在我们来看看效果

请修改部分代码center_image

其效果为center_image

很显然,这个太小了

我们用transform来调整大小

我以前的帖子里说的是pygame.transform.喵oothscale(),但是这个在低分辨率图片中效果不好

所以我们改用pygame.transform.scale()

我们图片的大小是18*27,长宽比为2:3,不妨改为22*33

tankImages = [pygame.transform.scale(pygame.image.load("assets/image/myTank.png"),(22,33)),pygame.transform.scale(pygame.image.load("assets/image/enemyTank.png"),(22,33))]

代码如图所示

请注意,改变图片大小后会导致角色矩形与图片不符,所以我们也要改变rect

center_image

大概这么大

运行后,可以发现大小大了一点,但至少比以前要好

至于为什么不用更大的大小,我们以后的帖子会提到

接下来我们加上移动喵的代码

喵移动是靠键盘上下左右键操控的,所以我们先在循环中加入

while keepGoing:
	doingTime+=1
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			keepGoing = False
		if event.type == pygame.KEYDOWN:
			if event.key == pygame.K_LEFT:
				pass
			if event.key == pygame.K_RIGHT:
				pass
			if event.key == pygame.K_UP:
				pass
			if event.key == pygame.K_DOWN:
				pass

	myTank.playerUpdate(screen)
	pygame.display.update()
	timer.tick(32)

exit()

这四个键代表不同方向的移动

不同方向的移动需要喵图片不同的朝向

在此,我们用pygame.transform.rotate()来改变朝向

这个方法需要两个参数,图片和角度

不过在此之前,我们需要一个变量表示方向,以及一个旋转的原料

	def __init__(self,x,y,image):
		self.x = x
		self.y = y
		self.speed = 3
		self.image = image
		self.tankImage = image
		self.facing = 0
		self.rect = pygame.Rect(self.x+5,self.y+14,12,14)

即上图中的tankImage和facing

这里的旋转机制有点复杂,代码如下

class player:
	def __init__(self,x,y,image):
		self.x = x
		self.y = y
		self.speed = 3
		self.image = image
		self.tankImage = image
		self.facing = 0
		self.rect = pygame.Rect(self.x+5,self.y+14,12,14)
	def playerUpdate(self,screen):
		if self.facing == 0:
			self.rect = pygame.Rect(self.x+5,self.y+14,12,14)
		elif self.facing == 1:
			self.rect = pygame.Rect(self.x+3,self.y+5,14,12)
		elif self.facing == 2:
			self.rect = pygame.Rect(self.x+5,self.y+3,12,14)
		elif self.facing == 3:
			self.rect = pygame.Rect(self.x+14,self.y+5,14,12)

		self.image = pygame.transform.rotate(self.tankImage,self.facing*90)
		screen.blit(self.image,(self.x,self.y))

myTank = player(100,200,tankImages[0])

while keepGoing:
	doingTime+=1
	screen.fill((0,0,0))
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			keepGoing = False
		if event.type == pygame.KEYUP:
			if event.key == pygame.K_LEFT:
				myTank.facing = 1
				myTank.x-=7
			if event.key == pygame.K_RIGHT:
				myTank.facing = 3
				myTank.x+=7
			if event.key == pygame.K_UP:
				myTank.facing = 0
				myTank.y-=7
			if event.key == pygame.K_DOWN:
				myTank.facing = 2
				myTank.y+=7

	myTank.playerUpdate(screen)
	pygame.display.update()
	timer.tick(32)

exit()

主要思想是旋转过后坐标,大小,矩形都要改变,具体变化数值请参考如上代码

然后我们的设定是按键盘控制方向,按ws控制移动,按空格控制开炮

开炮的代码现在不弄,控制键盘的代码已经弄好了,所以我们做ws控制移动的代码

这就需要控制坐标移动的变量,即xChange,yChange

也要记得每次更新改变坐标

代码如下

class player:
	def __init__(self,x,y,image):
		self.x = x
		self.y = y
		self.speed = 3
		self.image = image
		self.tankImage = image
		self.facing = 0
		self.xChange = 0
		self.yChange = 0
		self.rect = pygame.Rect(self.x+5,self.y+14,12,14)
	def playerUpdate(self,screen):
		self.x+=self.xChange
		self.y+=self.yChange
		if self.facing == 0:
			self.rect = pygame.Rect(self.x+5,self.y+14,12,14)
		elif self.facing == 1:
			self.rect = pygame.Rect(self.x+3,self.y+5,14,12)
		elif self.facing == 2:
			self.rect = pygame.Rect(self.x+5,self.y+3,12,14)
		elif self.facing == 3:
			self.rect = pygame.Rect(self.x+14,self.y+5,14,12)

		self.image = pygame.transform.rotate(self.tankImage,self.facing*90)
		screen.blit(self.image,(self.x,self.y))

然后是判断ws键的代码

此时,我们只需要改变xChange,yChange即可

if event.type == pygame.KEYUP:
			if event.key == pygame.K_LEFT:
				myTank.facing = 1
				myTank.x-=7
			if event.key == pygame.K_RIGHT:
				myTank.facing = 3
				myTank.x+=7
			if event.key == pygame.K_UP:
				myTank.facing = 0
				myTank.y-=7
			if event.key == pygame.K_DOWN:
				myTank.facing = 2
				myTank.y+=7
			if event.key == pygame.K_w or event.key == pygame.K_s:
				myTank.xChange = 0
				myTank.yChange = 0
		if event.type == pygame.KEYDOWN:
			if event.key == pygame.K_w:
				myTank.xChange=[0,myTank.speed,0,-myTank.speed][myTank.facing]
				myTank.yChange=[-myTank.speed,0,myTank.speed,0][myTank.facing]
			if event.key == pygame.K_s:
				myTank.xChange=[0,-myTank.speed,0,myTank.speed][myTank.facing]
				myTank.yChange=[myTank.speed,0,-myTank.speed,0][myTank.facing]

同时为了调试方便,我们暂时在每次循环中给屏幕加上背景

center_image

这样,我们这次的任务就完成了

最终代码为

import pygame

width = 720
height = 540
fps = 32
title = 'tank war'

pygame.init()
screen = pygame.display.set_mode([width,height])
pygame.display.set_caption(title)
timer = pygame.time.Clock()

tankImages = [pygame.transform.scale(pygame.image.load("assets/image/myTank.png"),(22,33)),pygame.transform.scale(pygame.image.load("assets/image/enemyTank.png"),(22,33))]

keepGoing = True
doingTime = 0

class player:
	def __init__(self,x,y,image):
		self.x = x
		self.y = y
		self.speed = 3
		self.image = image
		self.tankImage = image
		self.facing = 0
		self.xChange = 0
		self.yChange = 0
		self.rect = pygame.Rect(self.x+5,self.y+14,12,14)
	def playerUpdate(self,screen):
		self.x+=self.xChange
		self.y+=self.yChange
		if self.facing == 0:
			self.rect = pygame.Rect(self.x+5,self.y+14,12,14)
		elif self.facing == 1:
			self.rect = pygame.Rect(self.x+3,self.y+5,14,12)
		elif self.facing == 2:
			self.rect = pygame.Rect(self.x+5,self.y+3,12,14)
		elif self.facing == 3:
			self.rect = pygame.Rect(self.x+14,self.y+5,14,12)

		self.image = pygame.transform.rotate(self.tankImage,self.facing*90)
		screen.blit(self.image,(self.x,self.y))

myTank = player(100,200,tankImages[0])

while keepGoing:
	doingTime+=1
	screen.fill((0,0,0))
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			keepGoing = False
		if event.type == pygame.KEYUP:
			if event.key == pygame.K_LEFT:
				myTank.facing = 1
				myTank.x-=7
			if event.key == pygame.K_RIGHT:
				myTank.facing = 3
				myTank.x+=7
			if event.key == pygame.K_UP:
				myTank.facing = 0
				myTank.y-=7
			if event.key == pygame.K_DOWN:
				myTank.facing = 2
				myTank.y+=7
			if event.key == pygame.K_w or event.key == pygame.K_s:
				myTank.xChange = 0
				myTank.yChange = 0
		if event.type == pygame.KEYDOWN:
			if event.key == pygame.K_w:
				myTank.xChange=[0,myTank.speed,0,-myTank.speed][myTank.facing]
				myTank.yChange=[-myTank.speed,0,myTank.speed,0][myTank.facing]
			if event.key == pygame.K_s:
				myTank.xChange=[0,-myTank.speed,0,myTank.speed][myTank.facing]
				myTank.yChange=[myTank.speed,0,-myTank.speed,0][myTank.facing]

	myTank.playerUpdate(screen)
	pygame.display.update()
	timer.tick(32)

exit()

想要继续学习pygame和游戏制作的请关注

id:小鹿工作室_天上的流星

本帖内的所有代码,思想仅供参考,请勿用于盈利用途


回复

上一页1 页 / 共 1下一页
昊宸呦西昊宸呦西

怎么运行啊

 

点赞0


评论


晓鼬晓鼬

center_imageCouldn't open?

点赞0


评论


名字是什么a名字是什么a

wow

点赞0


评论