一步一步完成坦克大战:一、游戏关键难点实现
写在前面
入园这么久以来,一直都是工作中遇到了问题,才在园子里找各位大神的博客看,从来没有自己写过。前段时间为了找工作,做了一些面试准备,看了一些书,才发现一直以来都对.NET的基础知识掌握的不够熟练,会导致很多问题。所以就想着向园子里的各位大佬学习,从写博客开始加强自己对基础知识的巩固,也以此来督促自己要不断的学习和总结。
为什么要写坦克大战呢?原因还是因为坦克大战非常适合面向对象编程,结合自己这段时间看《C#图解教程》这本书的理解,可以做到一个很好的项目实践,加深自己对类,类的构造函数、属性,类的继承,抽象类,虚方法,方法的重载等等基础知识的运用。
游戏实现思路
坦克大战的实现思路还是比较好想到的,大概可以分为3个步骤
1、可以通过绘图片的方式,在一个画布上根据坐标绘制我们要的元素,这些元素包括:玩家坦克、敌方坦克,玩家子弹,敌方子弹,道具,砖墙,草地等。
2、对于元素的动作,这些动作包括:玩家移动,敌方坦克移动,玩家子弹移动,敌方子弹移动,砖墙爆炸等等。可以设置一个定时刷新的时间,在这个时间内完成所有的动作,完成之后每个元素都产生新的坐标数据。
3、根据新的坐标数据在画布中绘制所有元素
游戏中的主要问题其实就集中在如何绘制元素,如何实现元素的动作(比如移动,射击,爆炸等),在本文中会先用面向过程的方式实现这些关键问题,后续再从面向对象的方式来实现游戏。
关键难点Demo实现
一、准备工作
- 游戏资源 。可以自己网上找找,也可以从我后续的源码中获取
- 需要具备一些.NET Winform 开发的基础知识
- 需要了解GDI编程的基础用法
二、绘制元素
1、首先创建一个项目TankWar.TestDemo,在vs中调整好窗口大小,黑色背景,大概就是下面这样
2、导入游戏资源:右键项目=>属性=》资源=》添加资源,把下载好的游戏资源全都导入进来,大概就是下面这样
3、绘制一个坦克图片
在窗体中初始化好我们需要的坦克图片,然后在窗体的Paint事件中添加绘制代码
//玩家坦克图片private static Image[] imgs_play = {Resources.p1tankU,Resources.p1tankD,Resources.p1tankL,Resources.p1tankR,};public Form1(){InitializeComponent();}/// <summary>/// 窗体绘制事件/// </summary>private void Form1_Paint(object sender, PaintEventArgs e){Graphics g = e.Graphics;g.DrawImage(imgs_play[0], 0, 0);//绘制图片到(0,0)位置,(0,0)对应的是图片imgs[0]的左上角}
View Code
运行效果大概是下面这样:
通过同样的方式我们可以在窗体中的不同坐标上绘制敌方坦克,子弹等等,第一个关键点绘制图片就完成了。
三、元素的动作
3.1坦克移动
根据实现思路,这里我们需要给窗体设置一个刷新时间,然后在这个时间内完成坦克的移动,再重新绘制坦克
- 首先添加一个timer控件到窗体中,并添加timer控件的事件,并在窗体构造函数中初始化timer
- 然后为窗体添加KeyDown事件,这里我对方向的定义为:W=》上,S=》下,D=》右,A=》左
假设每次坦克移动10个坐标,具体的代码实现如下:
public partial class Form1 : Form{//玩家坦克图片private static Image[] imgs_play = {Resources.p1tankU,Resources.p1tankD,Resources.p1tankL,Resources.p1tankR,};private int p_speed = 10;//玩家速度private int p_x = 0;//玩家x坐标private int p_y = 0;//玩家y坐标private int p_direction = 0;//玩家方向 0向上,1向下,2向左,3向右public Form1(){InitializeComponent();//初始化timerthis.timer1.Interval = 50;this.timer1.Enabled = true;}/// <summary>/// 窗体绘制事件/// </summary>private void Form1_Paint(object sender, PaintEventArgs e){Graphics g = e.Graphics;//g.DrawImage(imgs_play[0], 0, 0);//绘制图片到(0,0)位置,(0,0)对应的是图片imgs[0]的左上角 g.DrawImage(imgs_play[p_direction], p_x, p_y);}/// <summary>/// timer事件/// </summary>private void timer1_Tick(object sender, EventArgs e){// 对窗体进行重新绘制this.Invalidate();}/// <summary>/// 按下按键/// </summary>private void Form1_KeyDown(object sender, KeyEventArgs e){switch (e.KeyCode){case Keys.W:p_direction = 0;p_y = p_y - p_speed;break;case Keys.S:p_direction = 1;p_y = p_y + p_speed;break;case Keys.A:p_direction = 2;p_x = p_x - p_speed;break;case Keys.D:p_direction = 3;p_x = p_x + p_speed;break;}}}
View Code
以上代码就能让我们的坦克移动起来了
3.2坦克射击
当玩家按下K的时候,坦克射击子弹
- 初始化子弹的图片、子弹速度、和存储子弹的列表
- 添加一个发射子弹的方法,在KeyDown事件中按下K时,执行该方法
- 在timer事件中移动子弹,在窗体重绘实践中绘制子弹
public partial class Form1 : Form{//玩家坦克图片private static Image[] imgs_play = {Resources.p1tankU,Resources.p1tankD,Resources.p1tankL,Resources.p1tankR,};private int p_speed = 10;//玩家速度private int p_x = 0;//玩家x坐标private int p_y = 0;//玩家y坐标private int p_width = 60;//玩家图片宽度private int p_height = 60;//玩家图片高度private int p_direction = 0;//玩家方向 0向上,1向下,2向左,3向右private static Image imgs_pbullet = Resources.tankmissile;//子弹图片private int b_width = 17;//子弹图片宽度private int b_height = 17;//子弹图片高度private int b_speed = 15;//子弹速度(最好比paly大)private List<int[]> listBullet = new List<int[]>();//存放画布中的子弹public Form1(){InitializeComponent();//初始化timerthis.timer1.Interval = 50;this.timer1.Enabled = true;}/// <summary>/// 窗体绘制事件/// </summary>private void Form1_Paint(object sender, PaintEventArgs e){Graphics g = e.Graphics;//g.DrawImage(imgs_play[0], 0, 0);//绘制图片到(0,0)位置,(0,0)对应的是图片imgs[0]的左上角//绘制玩家坦克 g.DrawImage(imgs_play[p_direction], p_x, p_y);//绘制子弹 DrawPlayBullet(g);}/// <summary>/// timer事件/// </summary>private void timer1_Tick(object sender, EventArgs e){//每次重绘就移动子弹 PlayBulletMove();// 对窗体进行重新绘制this.Invalidate();}/// <summary>/// 按下按键/// </summary>private void Form1_KeyDown(object sender, KeyEventArgs e){switch (e.KeyCode){case Keys.W:p_direction = 0;p_y = p_y - p_speed;break;case Keys.S:p_direction = 1;p_y = p_y + p_speed;break;case Keys.A:p_direction = 2;p_x = p_x - p_speed;break;case Keys.D:p_direction = 3;p_x = p_x + p_speed;break;case Keys.K:AddPlayBullet(p_direction, p_x, p_y);break;}}/// <summary>/// 添加玩家子弹/// </summary>/// <param name="b_direction">子弹方向</param>/// <param name="p_x">玩家的x坐标</param>/// <param name="p_y">玩家的y坐标</param>private void AddPlayBullet(int b_direction, int p_x, int p_y){int b_x = p_x;int b_y = p_y;//因为图片的大小,玩家方向,需要调整下子弹的位置,让其再玩家前正中方switch (b_direction){case 0:b_x += (int)(Math.Abs(b_width - p_width) / 2);b_y -= imgs_pbullet.Height;break;case 1:b_x += (int)(Math.Abs(b_width - p_width) / 2);b_y += imgs_play[b_direction].Height;break;case 2:b_x -= imgs_pbullet.Width;b_y += (int)(Math.Abs(b_height - p_height) / 2);break;case 3:b_x += imgs_play[b_direction].Width;b_y += (int)(Math.Abs(b_height - p_height) / 2);break;}int[] _b = new int[4] { b_direction, b_x, b_y, b_speed };listBullet.Add(_b);}/// <summary>/// 绘制玩家子弹/// </summary>/// <param name="g"></param>private void DrawPlayBullet(Graphics g){foreach (var item in listBullet){g.DrawImage(imgs_pbullet, item[1], item[2]);}}/// <summary>/// 移动子弹/// </summary>private void PlayBulletMove(){foreach (var item in listBullet){switch (item[0]){case 0:item[2] -= item[3];break;case 1:item[2] += item[3];break;case 2:item[1] -= item[3];break;case 3:item[1] += item[3];break;default:break;}}}}
View Code
运行后的效果图如下:
3.3坦克的碰撞
坦克的碰撞可以看作是两个矩形图片存在了交集,我们可以使用Rectangle的IntersectsWith方法来判断两个矩形是否有交集。
接下来我们按照上面3.1,3.2的方式绘制一些敌方坦克,然后在timer事件中执行碰撞的检测,并执行绘制爆炸效果
代码稍微比较长,这里直接上效果图
到这里,坦克大战游戏的关键难点就基本实现了,后面将会用面向对象的方式来实现整个游戏
源码下载
本文的内容对应解决方案中的TankWar.TestDemo项目
Github:https://github.com/Okarlchen/TankWar
转载于:https://www.cnblogs.com/FlareDream-KarlChen/p/10049842.html
一步一步完成坦克大战:一、游戏关键难点实现相关推荐
- 坦克大战小游戏关键技术总结
这两天参照韩顺平的坦克大战游戏并在其基础上初步完善成一个小的页面游戏,最终js代码大约570行,html代码200多行,具体可参见https://github.com/Mrkaiyang/Art/tr ...
- 使用《红孩儿工具箱》开发基于Cocos2d-x的《坦克大战》游戏
大家好,我是红孩儿.上一节我们学习了使用<红孩儿工具箱>开发<打地鼠>游戏.这一节我们继续学习使用<红孩儿工具箱>来开发<坦克大战>游戏. <坦克 ...
- C++实用编程——坦克大战小游戏
C++实用编程--坦克大战小游戏 Warning: 转载类 原文地址:*HTML https://yq.aliyun.com/articles/683666 改变速度的玩意坏了 我们直接看代码吧,适于 ...
- JAVA 实现《坦克大战》游戏|CSDN创作打卡
前言 小时候大家都玩过坦克大战吧,熟悉的旋律和丰富的关卡陪伴了我们一整个寒暑假,还记得传说中的经典坦克大战 吗?那些怀旧的记忆,伴随着我们一起走过来的经典坦克大战,刚开始那战战兢兢,屡屡被敌人坦克击毁 ...
- Unity双人坦克大战竞速游戏,超简单教学
好久没更新了,最近在研究unity,这个游戏已经做了好久了一直没发出来,我现在想开发一款猛鬼深林游戏,目前已经开发到新建文件夹了 话不多说,开始我们今天的主题,双人坦克大战竞速游戏 首先创建一个地形, ...
- Java实现的经典坦克大战小游戏
Java实现的经典坦克大战小游戏 先看一下游戏结构: 有点多,没有耐心的可以不用看,这里先给出链接吧! 云链接:经典坦克大战 提取码:s9ai 这里就不介绍功能了,贴了一张游戏运行的截图,具体的功能自 ...
- canvas+js实现简单的坦克大战小游戏
使用canvas和js实现经典的坦克大战并不难,坦克和炮弹的绘制可以使用canvas的里API画出,而坦克的移动和炮弹的发射可以依赖于键盘事件和定时器来实现. 在这里我要实现的坦克大战是双人模式,有木 ...
- 【JAVA程序设计】基于JAVA的坦克大战小游戏--入门级小游戏
基于JAVA的坦克大战小游戏--入门级小游戏 零.项目获取 一.项目简介 二.开发环境 三.游戏玩法 四.运行截图 零.项目获取 获取方式(点击下载):是云猿实战 项目经过多人测试运行,可以确保100 ...
- 《HTML5经典坦克大战》游戏(代码)
前几天粗略地学了HTML5,然后就用它写了一个<经典坦克大战>游戏. 现在想分享一下我写的代码,写得不好请大家多多指教. 给大家推荐一个网站,这个网站是为大学生而做,为方便学习编程的同学而 ...
- html实现经典坦克大战小游戏
文章目录 1.设计来源 1.1 游戏主界面 1.2 游戏界面 2.效果和源码 2.1 动态效果 2.2 源代码 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/w ...
最新文章
- 【量化投资】策略七(聚宽)
- Windows服务器版本简介
- 计算机网络的体系结构与协议基本概念,计算机网络技术基础-第3章网络体系结构与协议.ppt...
- 最强N皇后JAVA解题代码
- 简单的hibernate环境搭建、自动生成model/配置/hibernate.xml配置文件
- javascript 数字精度问题
- %12d在c语言中的意思,《C语言程序设计》习题.doc
- npm、cnpm、yarn的安装与常用命令
- VALSE学习(十四):自主学习
- Scrapy爬虫进阶操作之CrawlSpider(一)
- 网页实现语音对讲_GB28181实现摄像头语音对讲 - web音频采集调用示例
- velocity语法
- 精心梳理二十二道常见SSM面试题(带答案)
- URI和URL的概念和区别
- 生成对抗网络(十)----------infoGAN
- Windows Git 上传 报错 error: bad signature 0x00000000 fatal: index file corrupt
- ImageMagick convert命令
- linux 统一设备模型 pci,【原创】Linux PCI驱动框架分析(二)
- 转】基于GeoServer的电子地图系统说明(四):空间数据库实现
- linux c 编译 未定义的引用,c – Linux makefile中的未定义引用
热门文章
- python画xy轴折线在拐点处加汉字_解决python中画图时x,y轴名称出现中文乱码的问题...
- python全局变量怎么删除_python 全局变量怎么改
- 计算机领域中所谓课机是指,1.计算机基础知识题及答案
- linux ping 虚拟网卡_虚拟机中Linux系统网卡的配置
- socket通信基础
- python格式输出占四列左对齐_python – 打印字符串左对齐,固定宽度和后缀
- 什么是13薪,真的有18薪、25薪的不?
- T系统和应用集成-从SOA架构思想到服务架构规划设计
- 创想云教育9月公益直播课资料
- Windows学习总结(14)——最常用的Windows快捷键再总结