[python] 开发一个跟随角色移动的地图游戏demo

本文详细介绍如何使用Python和Pygame库创建2D角色游戏的地图原型,包括游戏框架搭建、地图绘制、角色移动及动画实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用python开发一个2D角色游戏的地图Demo

如今很多大学生大学学习了编程语言,想做游戏却迟迟做不出一个游戏雏形来,接下来就和大家谈论下游戏中地图移动的简单原理并用python这一门非常火的语言进行详细的描述。

游戏使用python开发

为什么用python开发,因为python简单易学,对于初学者来说非常适合,而且python集成的库非常地多,我们这里采用python的安装库pygame进行开发。

首先你需要已经安装了python并且已经下载了pygame库

打开你所熟悉的Sublime Text文本编辑器,或者其他的文本编辑器【记事本也可以】创建好一个python开发文件,如下图:
在这里插入图片描述
游戏中pygame的框架雏形如下代码:


```python
import pygame,sys
pygame.init()
screen = pygame.display.set_mode([840,550],0,32)
screen_caption = pygame.display.set_caption('game')
pygame.display.flip()
while True:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      sys.exit()
  pygame.display.update()

代码运行如图:
在这里插入图片描述
一个白板啥也没有这就对了,说明游戏搭建成功!

代码解释

解释:
代码中第一行是导入pygame游戏库,其最初的雏形是SDL。
它包含图像、声音,pygame建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。基于这样一个设想,所有需要的游戏功能和理念都(主要是图像方面)都完全简化为游戏逻辑本身,所有的资源结构都可以由高级语言提供,如Python。
Pygame 原为代替突然停止的 pySDL。
这就是为什么选择python这个库pygame来开发游戏,而不是c语言。
pygame.init()是导入所有pygame方法。

screen = pygame.display.set_mode([840,550],0,32)

#代码是创建屏幕窗口宽840像素,高550像素,不全屏的窗口。

screen_caption = pygame.display.set_caption('game')

代码是写一个窗口的标题

pygame.display.flip()

代码是刷新屏幕,可以意味更新屏幕内容

while True:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      sys.exit()
  pygame.display.update()

while True是死循环的意思,在游戏中程序就是一个死循环,当游戏结束时就让程序终结循环即可。这是游戏运行的原理。
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
这几行即便是获取游戏中用户输入的状态,if中捕获退出消息的状态,如果是退出窗口,那么就执行sys库中的exit()方法来结束游戏程序。
最后一行的pygame.display.update()也可意味刷新屏幕。

说到这里大家就会问了,pygame.display.flip()和 pygame.display.update()都是刷新,那二者有什么区别吗,其实也没太大的区别,update()是更新部分软件界面显示,而flip()更新整个待显示的Surface对象到屏幕上了,这里我们死循环中用到update()而不是flip()是为了更好的让游戏流畅,节省内存而已。

闲话不多说,我们步入正规

首先导入我的所用的所有库

# -*- coding:utf-8 -*-
import pygame,os,wx
from pygame.locals import *
from sys import exit
from random import randint
pygame.init()

在这里建议下载一个叫做wx的库,这是用来写gui图形界面软件的库,我们用它来获得屏幕的大小好以后开发维护提供遍历条件。

接下来我的一切内容都会写入main方法中,整个main方法框架如下:

...省略了导入的库
def main():
	pass
if __name__ == '__main__':
	main()

pass就是空语句,接下来我会在main方法中填入所有的游戏内容。以上省略了导入的库

在此我们需要用到下面的地图资源文件
在这里插入图片描述

两个图都是我自己画的,虽然不是很好看但是能用就行

然后角色我是下载的网上的,包括了个方位行走的动作帧图如下:
在这里插入图片描述
这张图是不是比我画的不晓得好到哪儿去了,呃…。不管这些了,然后继续上我的代码:

别忘了代码都写在main函数中,下面基本都有注释记得稍微看看哦

	app=wx.App()#创建wx.App
	WHSIZE=wx.DisplaySize()#获取屏幕大小
	WHSIZE=int(WHSIZE[0]*0.75),int(WHSIZE[1]*0.85)#变成屏幕宽度75%,变成屏幕高度的85%
	Mapxy=950,950,-950,-950	地图宽度从950-950高度也是一样 
	ax,ay=0,0#看作是角色的左上角位置
	screen=pygame.display.set_mode([WHSIZE[0],WHSIZE[1]],0,32)#载入屏幕上面讲到过
	caption=pygame.display.set_caption('project1')#屏幕标题
	bg=pygame.image.load('image/map/bg1.png').convert_alpha()#地图壁纸
	tree=pygame.image.load('image/map/tree.png').convert_alpha()#地图中的树
	man=pygame.image.load('image/pic/哥布林/145118l0哥布林_01.gif').convert_alpha()#载入哥布林角色图片
	manxy=man.get_width(),man.get_height()#哥布林的尺寸
	manxy=WHSIZE[0]/2-manxy[0]/2,WHSIZE[1]/2-manxy[1]/2#让哥布林的位置变成地图的正中央
	man_direction='down'	#哥布林的方向默认为向下的方向
	man_walk_time=0			#哥不林移动的时间
	map_tree_list=[]#随机树列表
	for i in range(500):#随机生成500个树的位置
		map_tree_list.append([randint(50, 65),randint(50, 65)])
	pygame.key.set_repeat(20)#让按键一直响应【就只一直按着一个键不松开,就会一直响应】
	screen.fill([0,0,0])#屏幕初始化填充为黑色
	pygame.display.flip()#刷新屏幕

**接下来是一个游戏的主体【也就是写在死循环里面】下面和一段是接受按键信息来控制地图拖动和哥布林移动的算法。

#外设事件判断
		for event in pygame.event.get():
			if event.type==QUIT:#按键判断是否退出游戏
				exit()
			if event.type==KEYDOWN:
						#地图拖动和主角相反
				if event.key==K_UP:
					ay+=100
					man_direction='up'
					man_walk_time+=1
				if event.key==K_DOWN:
					ay-=100
					man_direction='down'
					man_walk_time+=1
				if event.key==K_LEFT:
					ax+=100
					man_direction='left'
					man_walk_time+=1
				if event.key==K_RIGHT:
					ax-=100
					man_direction='right'
					man_walk_time+=1
			if event.type==KEYUP:
				if event.key==K_UP:
					man_walk_time=0
					man=pygame.image.load('image/pic/哥布林/145118l0哥布林_13.gif').convert_alpha()
				if event.key==K_DOWN:
					man_walk_time=0
					man=pygame.image.load('image/pic/哥布林/145118l0哥布林_01.gif').convert_alpha()
				if event.key==K_LEFT:
					man_walk_time=0
					man=pygame.image.load('image/pic/哥布林/145118l0哥布林_05.gif').convert_alpha()
				if event.key==K_RIGHT:
					man_walk_time=0
					man=pygame.image.load('image/pic/哥布林/145118l0哥布林_09.gif').convert_alpha()
		#外设事件判断结束

在我设计的地图中宽度是宽高是1900,1900,也就是从坐标(-950,-950)到(950,950),屏幕正好是(0,0)的位置不会变,也就形成了哥布林在整个地图中央的逻辑

如下图:
在这里插入图片描述
接着下面的代码是用来绘制surface放到屏幕上:

		screen.fill([0,0,0])	#绘制整个游戏背景为黑色
		#把事先的绿色地块用来填满整个地图,绘制地图所有方块2000像素的地图
		for i in range(int(2000/50)):
			for j in range(int(2000/50)):
				screen.blit(bg,( (-1000+WHSIZE[0]/2)+(50*j)+ax,(-1000+WHSIZE[1]/2)+(50*i)+ay ))

		#绘制地图外圈的环境,也就是绘制之前随机的地图树,用四个for循环绘制
		for i in range(52):
			for j in range(7):
				screen.blit( tree ,( -1100+(i*map_tree_list[i*j][0])+ax, -1100+(j*map_tree_list[i*j][1])+ay ))
				screen.blit( tree ,( -1100+(i*map_tree_list[i*j][0])+ax, 1300+(j*map_tree_list[i*j][1])+ay ))
		for i in range(10):
			for j in range(50):
				screen.blit( tree ,( -1100+(i*map_tree_list[i*j][0])+ax, -1100+(j*50)+ay ))
				screen.blit( tree ,( 1450+(i*map_tree_list[i*j][0])+ax, -1000+(j*50)+ay ))

上面用四个for循环绘制树的地图,绘制之后会有他的魔力的,我们待会儿见证

我们都知道在2D游戏中,地图中的角色是不是不管怎么走都不会越过地图之内,永远都不会超出地图之外呢?

那么接下来我们需要判断一个碰壁弹回的方法,如下代码

		#出界判断
			#左,上
		if ax>=Mapxy[0]:
			ax=Mapxy[0]
		if ay>=Mapxy[1]:
			ay=Mapxy[1]
			#右,下
		if ax<=Mapxy[2]:
			ax=Mapxy[2]
		if ay<=Mapxy[3]:
			ay=Mapxy[3]

ax,ay就是哥布林角色的左上坐标,Mayxy就是地图的四个坐标【左上角,和右下角】(x1,y1,x2,y2)

接着,我们需要绘制哥布林随着方向移动而改变它的帧图
原理如下:
最开始角色的方向是向下的
在这里插入图片描述
如上图方向的变量是“down”,如果方向是向上边"up",左边“left”,右边“right”
每一个方向有几个四个动作,整合起来如下
在这里插入图片描述
每个动作占时100毫秒,接下来我们会在程序的最后面写入延迟delay(100),当每个动作都设置好,每个动作的每一帧都播放一段时间,然后循环播放就形成了我们人眼中所看到的动画片,这里插播一下: 游戏就是动画片的一种多元化陈述。
在这里插入图片描述
如上图就是图片轮询播放从而事先了动画片的效果,是不是很有趣呢,不过在好看的前提下我们的设计师是有很大的作用哦!!!

如下程序就判断绘制了所有方向所有的动作帧

		#人物绘制和行走
		if man_direction=='up':
			if man_walk_time==1:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_14.gif').convert_alpha()
			if man_walk_time==2:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_15.gif').convert_alpha()
			if man_walk_time==3:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_16.gif').convert_alpha()
				man_walk_time=0

		if man_direction=='down':
			if man_walk_time==1:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_02.gif').convert_alpha()
			if man_walk_time==2:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_03.gif').convert_alpha()
			if man_walk_time==3:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_04.gif').convert_alpha()
				man_walk_time=0

		if man_direction=='left':
			if man_walk_time==1:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_06.gif').convert_alpha()
			if man_walk_time==2:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_07.gif').convert_alpha()
			if man_walk_time==3:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_08.gif').convert_alpha()
				man_walk_time=0

		if man_direction=='right':
			if man_walk_time==1:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_10.gif').convert_alpha()
			if man_walk_time==2:
				man=pygame.image.load'(image/pic/哥布林/145118l0哥布林_11.gif').convert_alpha()
			if man_walk_time==3:
				man=pygame.image.load('image/pic/哥布林/145118l0哥布林_12.gif').convert_alpha()
				man_walk_time=0

		screen.blit(man,(manxy))
		#人物绘制和行走结束

看如上代码是不是很简单。

最后是程序的结尾刷新和延迟

		pygame.display.update()	#更新屏幕
		pygame.time.delay(100)	#100表示延迟100毫秒

到此整个游戏demo就完成,我么来操作控制台运行游戏如下
在这里插入图片描述
在控制台输入:
在这里插入图片描述
敲击回车运行游戏如下:
在这里插入图片描述
右边的移动和行走如下:
在这里插入图片描述
看是不是很有成就感,不过这个游戏有很多地方可以优化的,看看广大朋友们有什么好的算法和方法优化一定要联系我哦,如需要源代码和素材的可以联系,免费提供,开源交流,一步一步看我变强变凸。

<think>好的,我现在需要帮用户拆解制作似《极简塔防》的Demo需要先做哪些东西。首先,用户可能是一个刚入门的游戏开发者,或者是对塔防游戏制作感兴趣的新手。他们可能已经玩过《极简塔防》,觉得不错,想自己尝试做一个似的Demo,但不知道从哪里下手。这时候,用户的需求不仅仅是步骤列表,更需要一个结构化的指导,帮助他们理清优先级和关键点。 首先,我需要回想之前用户关于拆解《极简塔防》核心玩法的回答,里面提到了核心循环、防御塔系统、敌人设计、资源经济、地图机制等。制作Demo的话,应该先聚焦最核心的部分,避免一开始就陷入复杂系统。这时候可能需要先确定MVP(最小可行产品)包含哪些元素。 接下来,用户可能没有太多开发经验,所以需要给出具体的步骤,并且可能涉及到技术选型,比如引擎的选择。这时候需要推荐简单易用的工具,比如Unity或Godot,或者如果用户擅长编程,可能用Phaser.js等框架。同时,美术资源方面,用户可能没有专业的美术能力,所以建议使用原型方块或免费资源,降低初期门槛。 然后,分步骤思考。第一步是核心玩法原型,这是Demo的基础,必须确保基础循环跑通,比如敌人生成、移动,防御塔的放置和攻击。这部分需要最基础的代码实现,比如敌人的路径跟随,防御塔的检测和攻击逻辑。 第二步是基础系统框架,包括经济系统和敌人波次系统。经济系统需要管理金币的获取和消费,敌人波次需要控制生成逻辑和难度递增。这里可能需要一些简单的公式,比如每波敌人数量或属性的增长。 第三步是防御塔和敌人的基础实现。防御塔的型可能不需要太多,但至少要有两种不同的型,比如单体攻击和范围攻击。敌人的属性如移动速度、生命值也需要配置,可能通过脚本ableObject来管理数据,这样调整起来方便。 第四步是地图编辑器的搭建,或者至少是路径的设计。用户可能需要使用Tilemap工具来绘制地图,设置路径点,确保敌人能正确移动。动态路径可能比较复杂,初期可以固定路径,后续再扩展。 第五步是UI和反馈,比如金币显示、生命值、波次信息等。这些对于玩家的体验很重要,但初期可以用简单的文本显示,之后再美化。 第六步是调试和优化,确保没有明显bug,性能问题,比如敌人数量多时的卡顿,可能需要对象池技术。最后是扩展准备,考虑之后如何添加更多内容。 在思考过程中,需要注意用户可能的痛点,比如技术实现上的难点,如何管理敌人和防御塔的交互,如何设计路径算法,或者如何处理升级系统的数值平衡。这时候需要给出具体的建议,比如使用射线检测或触发器来处理攻击范围,使用协程或状态机管理敌人行为。 另外,用户可能对资源管理不太清楚,比如如何高效管理不同的敌人和防御塔型,这时建议使用ScriptableObject或配置文件,这样方便调整和扩展。 最后,要提醒用户保持简单,逐步迭代,先做出可玩的Demo再逐步添加功能,避免一开始就追求完美,导致项目无法完成。同时,推荐一些学习资源或工具,帮助他们进一步学习。</think>制作似《极简塔防》的游戏Demo可遵循以下开发路径(附关键实现逻辑): --- ### 一、核心玩法原型(优先级最高) 1. **基础循环搭建** ```csharp // Unity伪代码示例 void SpawnEnemyWave(int waveNumber){ for(int i=0; i<3 + waveNumber*2; i++){ Instantiate(enemyPrefab, spawnPoint); } } ``` - 必需组件:敌人移动路径系统(A*算法或NavMesh) - 基础交互:防御塔点击放置功能 - 数值验证:单防御塔能否拦截基础敌人 2. **敌人路径系统** - 实现方案:通过`Transform[] waypoints`存储路径点 - 移动逻辑: ```python # 伪代码示例 def enemy_update(): target_pos = waypoints[current_index] if distance < 0.1: current_index +=1 else: position += direction * speed * delta_time ``` --- ### 二、基础系统框架 1. **经济系统** | 事件型 | 数值变化公式 | 实现方式 | |-----------------|-----------------------|------------------------| | 击杀奖励 | gold += base * (1 + 0.1*wave) | 敌人死亡事件触发 | | 漏怪惩罚 | hp -= damage * (1 + 0.05*missed) | 碰撞检测到终点触发 | 2. **波次控制器** ```javascript // 伪代码示例(波次间隔公式) function getWaveInterval(wave){ return Math.max(5, 15 - wave*0.3); } ``` --- ### 三、防御塔实现 1. **攻击逻辑核心代码** ```csharp void Update(){ if(target == null) FindTarget(); if(Time.time > nextAttackTime){ ShootProjectile(); nextAttackTime = Time.time + 1f/attackRate; } } ``` - 攻击型实现差异: - 单体攻击:`Physics.Raycast` - 范围攻击:`Physics.OverlapSphere` 2. **升级系统数据结构** ```json { "towerLevels": [ {"damage":10, "cost":50, "range":3}, {"damage":15, "cost":75, "range":3.5} ] } ``` --- ### 四、敌人行为实现 1. **基础属性配置表** | 敌人型 | 生命值公式 | 速度 | 特殊能力 | |----------|------------------|------|------------------| | 普通 | 10*(1.1^wave) | 1.2 | 无 | | 快速 | 5*(1.05^wave) | 2.5 | 闪避率10% | 2. **死亡事件处理** ```csharp void OnDeath(){ GameManager.AddGold(reward); if(hasSpawnChildren){ Instantiate(minion, transform.position); } } ``` --- ### 五、开发工具链建议 1. **快速原型工具** - 路径编辑:Unity的`CinemaMachine`或自定义编辑器工具 - 数值调试:Unity的`ScriptableObject`数据容器 - 特效占位:使用`Primitive`几何体+粒子系统基础效果 2. **性能优化重点** - 对象池管理敌人实例 - 使用Jobs System处理大量弹道计算 - 避免每帧执行`FindGameObjectsWithTag` --- ### 六、开发里程碑建议 1. **Week1**:完成核心循环(敌人沿路径移动+单防御塔攻击) 2. **Week2**:实现经济系统+3种基础防御塔 3. **Week3**:加入波次控制+基础UI界面 4. **Week4**:完成首张可玩地图+平衡性测试 建议初期采用敏捷开发模式,每完成一个模块立即进行玩法验证(如使用Unity的Play Mode测试),重点保持核心循环的流畅性大于画面表现。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值