程序地址:网页链接

注意:目前只支持win系统。

游戏做的不完整,只能用来体验体验。

最近接触了Pygame游戏编程,十分感兴趣,学习了一本相关书籍以及查阅了Pygame的官网https://www.pygame.org的资料,花了一周的时间写出了这个飞机大战的游戏。主体玩法相对完整,模拟的是逝去的手游帝王《雷霆战机》,算是对它多舛命运的哀悼吧。

话不多说,先看效果

什么,你问我素材哪里找的?万能的淘宝在这时候总不会让你失望!所有音频和图片素材均来自于淘宝。

这里跟大家分享几个制作过程中遇到的几个技术细节的解决方法,以及优化措施:

1.帧率不同步问题。

我用pygame.time.Clock对象来控制整个游戏的最大帧率为60。为什么说是最大呢?不是因为性能原因导致游戏帧率真的低于60(虽然在某些过程优化之前的确出现过卡的低于60帧的情况),是因为某些动画过程的帧率本就不是60,比如飞机爆炸的动画,就那么9帧,若60Hz播放的话就显得太快了,起初,我想到用重复的图片Surface对象填充这些应该重复的几帧,使得切换到下一帧的速度没那么快,但重复的图片对象会导致成倍数的内存占用,这是我不能忍受的。于是我用了一个FramNum对象,将重复的次数用正整数num表示,并增加计数点属性,当运行到下一次就增加一个计数点,若计数点达到了num,则运行下一帧。于是一个完整的动画帧Frame对象被设计成由FramNum对象组成,能够成倍数地减少在动画帧方面内存使用。

以下实现代码看不懂没关系,因为注释不清楚,而且有一些额外的设计没有被提及。

import pygameclass FrameNum:def __init__(self, frame:pygame.Surface, num:int):self.frame = frameself.num   = numdef __getframe(self):return self.__framedef __setframe(self, other):self.__frame = otherframe = property(__getframe, __setframe)def __getnum(self):return self.__numdef __setnum(self, other):self.__num = othernum = property(__getnum, __setnum)def __mul__(self, other):self.num *= otherreturn selfdef __imul__(self, other):self.num *= otherreturn selfdef __getitem__(self, item):if item == 0:return self.frameelif item == 1:return self.numelse:raise ValueError('indexvalue not 0 or 1!')class Frame:'like [[(frame1,num1),(frame2,num2)],[...]]'LASTCIRCLE= b'\x01'LASTSTICK = b'\x00'def __init__(self, framelist, leisureframe=0):self.framelist  = framelist# this conditionself.this_code  = leisureframeself.thiscondition = framelist[self.this_code]# this condition lenself.thiscdlen  = len(self.thiscondition)# this frameself.thisframe  = 0# this frame numself.thisfnum   = self.thiscondition[self.thisframe][1]self.thisgone   = 0self.image      = self.thiscondition[self.thisframe][0]self.next_code  = self.LASTCIRCLEself.sticked    = False# 得到本状态的虚拟帧数目self.leisureframe = leisureframedef set_stick(self):self.next_code = self.LASTSTICKdef unsetonce(self):self.next_code = self.LASTCIRCLEdef update(self):# 若为循环播放if not self.sticked:if self.next_code == self.LASTCIRCLE:self.circleupdate()elif self.next_code == self.LASTSTICK:self.stickupdate()else:self.onceupdate()def changecondition(self, condition_code):self.thiscondition = self.framelist[condition_code]self.thisgone   = 0self.thisframe  = 0self.this_code = condition_codeself.thiscdlen  = len(self.thiscondition)self.updateframe()# 跳转condition代码def set_next(self, next_code):self.next_code = next_codedef set_condition(self, this_code):self.this_code = this_codedef circleupdate(self):# 若达到这一帧的最后一个if self.thisgone >= self.thisfnum:# 进入下一帧self.nextframe()# 若超过最后一帧if self.thisframe >= self.thiscdlen:self.thisframe = 0self.thisgone = 0# 图像变化self.updateframe()# 下一个虚帧self.go()def stickupdate(self):if self.thisframe < self.thiscdlen - 1:if self.thisgone >= self.thisfnum - 1:self.nextframe()self.updateframe()else:self.go()elif self.thisframe == self.thiscdlen - 1:if self.thisgone < self.thisfnum - 1:self.go()else:if not self.sticked:self.sticked = Truedef onceupdate(self):if not self.thisframe == self.next_code:if self.thisframe < self.thiscdlen - 1:if self.thisgone >= self.thisfnum:self.nextframe()self.updateframe()self.go()else:if self.thisgone >= self.thisfnum:self.changecondition(self.next_code)else:self.go()def set_certain(self, new_thisframe, new_condition_code, sticked=False):self.this_code = new_condition_codeself.thisframe = new_thisframeself.thiscondition = self.framelist[self.this_code]self.updateframe()self.thiscdlen = len(self.thiscondition)self.thisgone = 0self.next_code = self.LASTSTICK if sticked else self.LASTCIRCLEself.sticked = Falsedef nextframe(self):self.thisgone = 0self.thisframe += 1def updateframe(self):self.image = self.thiscondition[self.thisframe][0]self.thisfnum = self.thiscondition[self.thisframe][1]def go(self):self.thisgone += 1def copy(self):return Frame(self.framelist, self.leisureframe)

2.按钮制作

按钮是和鼠标放上和鼠标点击时间交互的精灵对象,我用两个旗帜onCovered和onClicked来保存鼠标放上和点击按钮的状态,并且鼠标放上将使按钮变得更亮,移开后按钮又恢复原状。点击按钮又是另一种动画帧。有了以上Frame对象管理帧,这个整体变得不难实现。

3.游戏开始前的背景

游戏开始前的背景是用29帧动画重复播放实现的

4.游戏背景循环滚动设计

正式进入游戏,希望能模拟飞机战场的推进,背景向下方不断滚动,并循环播放,此代码保证一次最多只渲染两个背景图片,当滚动出界时回到原处重复过程,能做到无缝衔接

最终游戏背景为如下VerticalUSBG对象

import pygame
from myGametools import mySprite
from myGametools import mypointclass BackGround(mySprite.MyMoveSprite):def draw(self, screen:pygame.Surface):screen.blit(self.image, self.rect)self.update()class UnStopBG(BackGround):def __init__(self, frame, position:mypoint.Mypoint, speed=0, accelerate=0):self.frame  = frameself.image  = self.frame.imageself.rect   = pygame.Rect(*position.position, *self.image.get_size())self.speed  = speedself.accelerate = accelerateclass LevelUSBG(UnStopBG):def draw(self, screen:pygame.Surface):lastrect = self.rectfor i in range(screen.get_width()//self.rect.width + 1):screen.blit(self.image, lastrect)lastrect.topleft = lastrect.toprightif self.speed > 0:if 0 < self.rect.left < self.rect.width:screen.blit(self.image, (self.rect.left-self.rect.width, self.rect.top))elif self.rect.left >= self.rect.width:self.rect.left = 0elif self.speed < 0:if lastrect.left <= screen.get_width():screen.blit(self.image, lastrect)if self.rect.right <= 0:self.rect.left = 0else:returnself.rect = self.rect.move(self.speed, 0)self.speed += self.accelerateclass VerticalUSBG(UnStopBG):def draw(self, screen: pygame.Surface):lastrect = self.rect.copy()for i in range(screen.get_height() // self.rect.height + 1):screen.blit(self.image, lastrect)lastrect.topleft = lastrect.bottomleftif self.speed > 0:if 0 < self.rect.top < self.rect.height:screen.blit(self.image, (self.rect.left, self.rect.top-self.rect.height, self.rect.width, self.rect.height))elif self.rect.top >= self.rect.height:self.rect.top = 0elif self.speed < 0:if lastrect.bottom <= screen.get_height():screen.blit(self.image, lastrect)if self.rect.bottom <= 0:self.rect.top = 0else:returnself.rect = self.rect.move(0, self.speed)self.speed += self.accelerate

5.玩家飞机操纵逻辑和飞机姿态转换逻辑

玩家飞机控制的最开始版本为飞机只有一个正面的姿态,没有侧翻的姿态,并且飞机不能加速,只能匀速运动,控制键为"wasd"系(w向前,a向左,s向后,d向右)

但这样玩起来十分枯燥,手感单一。于是想到模拟飞机控制的实际情景,为飞机添加加速度。如当玩家按下a时,飞机就像左加速,当玩家松开时,飞机就减速直到速度为0。而加速有一个最大值。并且要保证飞机不飞出窗口,由于编写飞机的过程中多次涉及到“限制”这个概念,于是想到写Bound类系:

import pygameimport sys
# bound族都有limit协议class BoundUnit:NEGATIVE_INFINITY = b'\x11'POSITIVE_INFINITY = b'\x01'def __init__(self, floor=NEGATIVE_INFINITY, ceiling=POSITIVE_INFINITY):self.__floor = floorself.__ceiling = ceilingself.__room = (floor, ceiling)def __getf(self):return self.__floordef __getc(self):return self.__ceilingdef __getroom(self):return self.__roomfloor = property(__getf)ceiling = property(__getc)room = property(__getroom)def floorlimit(self, other, eq=True):if self.floor == self.NEGATIVE_INFINITY:return Trueif eq:return self.floor <= otherelse:return self.floor < otherdef ceilinglimit(self, other, eq=True):if self.ceiling == self.POSITIVE_INFINITY:return Trueif eq:return other <= self.ceilingelse:return other < self.ceilingdef limit(self, other, eqf=True, eqc=True):return self.floorlimit(other, eqf) and self.ceilinglimit(other, eqc)def setin(self, other, eqf=True, eqc=True):if not self.floorlimit(other, eqf):other = self.floorelif not self.ceilinglimit(other,eqc):other = self.ceilingreturn otherdef __getitem__(self, item):return self.room[item]class BoundGroup:# 限制群def __init__(self, *groups):self.bounds = set(groups)def __add__(self, other):return self.bounds + other.boundsdef __radd__(self, other):return self + otherdef __iadd__(self, other):self.bounds += set(other)return selfdef limit(self, other):for i in self.bounds:if not i.limit(other):return Falsereturn Trueclass BoundLine:# 切割数轴的有序bound# 必须为升序def __init__(self, boundpoints):bounds = []self.boundlen = len(boundpoints) + 1if self.boundlen  == 1:bounds.append(BoundUnit(BoundUnit.NEGATIVE_INFINITY, BoundUnit.POSITIVE_INFINITY))else:bounds.append(BoundUnit(BoundUnit.NEGATIVE_INFINITY, boundpoints[0]))for i in range(self.boundlen-2):if not boundpoints[i] < boundpoints[i+1]:raise ValueError('please garantee its ascending order')bounds.append(BoundUnit(boundpoints[i], boundpoints[i+1]))bounds.append(BoundUnit(boundpoints[-1], BoundUnit.POSITIVE_INFINITY))self.bounds = boundsdef detect_section(self, other, righteq=True):for i in range(self.boundlen):if self.bounds[i].limit(other, not righteq, righteq):return iclass BoundLineSymmetry(BoundLine):def __init__(self, boundpoints):bounds = []boundpoints.reverse()negboundpoints = [-i for i in boundpoints]self.lefthalfbounds = BoundLine(negboundpoints)for i in negboundpoints:bounds.append(i)boundpoints.reverse()self.righthalfbounds  = BoundLine(boundpoints)if boundpoints[0]:bounds.append(boundpoints[0])for i in boundpoints[1:]:bounds.append(i)super().__init__(bounds)def detect_section(self, other, righteq=True):leftdetect = self.lefthalfbounds.detect_section(other, not righteq)rightdetect = self.righthalfbounds.detect_section(other, righteq)return leftdetect + rightdetectclass Boundlftb:# 目前不支持改变def __init__(self, bound_1: bound.BoundUnit, bound_2: bound.BoundUnit):self.__left = bound_1[0]self.__right = bound_1[1]self.__top   = bound_2[0]self.__bottom = bound_2[1]self.__leftright = bound_1.roomself.__topbottom = bound_2.roomself.bound_1 = bound_1self.bound_2 = bound_2self.__bound = (self.bound_1, self.bound_2)def __getl(self):return self.__leftdef __getr(self):return self.__rightdef __gett(self):return self.__topdef __getb(self):return self.__bottomdef __getlr(self):return self.__leftrightdef __gettb(self):return self.__topbottomleft = property(__getl)right = property(__getr)top = property(__gett)bottom = property(__getb)leftright = property(__getlr)topbottom = property(__gettb)def leftlimit(self, other, eq=True):return self.bound_1.floorlimit(other, eq)def rightlimit(self, other, eq=True):return self.bound_1.ceilinglimit(other, eq)def xlimit(self, other, eql=True, eqr=True):return self.bound_1.limit(other, eql, eqr)def toplimit(self, other, eq=True):return self.bound_2.floorlimit(other, eq)def bottomlimit(self, other, eq=True):return self.bound_2.ceilinglimit(other, eq)def ylimit(self, other, eqt=True, eqb=True):return self.bound_2.limit(other, eqt, eqb)def limit(self, x, y, xeqf=True, xeqc=True, yeqf=True, yeqc=True):return self.xlimit(x, xeqf, xeqc) and self.ylimit(y, yeqf, yeqc)def __getitem__(self, item):return self.__bound[item]

总之它们封装了可用于限制速度和飞机位置的代码,并在飞机的实现中用到

对于飞机的姿态问题也就迎刃而解了,就根据其向左或向右的速度区间,利用以上的数轴对称区间划分BuondLineSemmetry类来判断飞机速度所在区间,并确定将信息返回给飞机,使得飞机具备相应的状态stage属性,在根据该属性调整显示图片

6.飞机发射武器

武器可以看作子弹的群组,于是从pygame.sprite.Sprite继承了Bullet子弹类,从pygame.sprite.Group继承了Gun武器类。武器能间隔一段时间在飞机的固定的一些相对位置生成子弹,因此武器也需要和飞机绑定配置在一起。于是飞机和武器又是has-a关系。注意到飞机的组成如此复杂,为了避免写出有极多属性的飞机类,于是用ControlCenter控制中心类来封装飞机的运动,并用Engine类封装飞机运动的控制:

# controlcenter.py
import random
import pygame
from . import engine
from classes import bound, boundlrtb
from init import constants
from init import globalsInitclass ControlCenter:'''manage move and location'''def __init__(self, engine:engine.Engine):# engine only manage speed changing and accelerate changingself.engine = engine# 预加载screen_bound 免得每次都重复生成self.space_b = globalsInit.screen_bounddef configure(self, plane):# 初始位置self.plane = planeself.rect = pygame.Rect(int(constants.SCREEN_SIZE[0] / 2 - plane.rect.width),int(constants.BeginLocCEnter - plane.rect.height / 2),plane.rect.width,plane.rect.height)plane.rect = self.rectdef control(self):self.engine.drive()self.updatelocation()self.plane.rect = self.rectdef updatelocation(self):if not self.space_b.leftlimit(self.rect.left, True):self.rect.left = self.space_b.leftelif not self.space_b.rightlimit(self.rect.right, True):self.rect.right = self.space_b.rightif not self.space_b.toplimit(self.rect.top, True):self.rect.top = self.space_b.topelif not self.space_b.bottomlimit(self.rect.bottom, True):self.rect.bottom = self.space_b.bottomself.rect.left += self.engine.speed[0]self.rect.top += self.engine.speed[1]def copy(self):return ControlCenter(self.engine.copy())class Enemy_Controlcenter(ControlCenter):def configure(self, plane):self.plane = planeself.rect = plane.rectclass Sa_1_Controlcenter(Enemy_Controlcenter):
# 敌人的中央控制器def control(self):if self.rect.bottom < 0:self.engine.a_acce()else:super().control()# engine.py
import pygame, random
from pygame.locals import *
from myGametools import mymove
from classes import boundlrtb, bound
from classes.planes import planeclass Engine(mymove.Mymove):# only for speed and accelerate(manally, just for player)# 目前在Engine类中硬编码所有飞船都应遵守的协议ACCE_x  = 1ACCE_y  = 0.2ACCE_F  = 0.5LEFT = 0LEISURE = 1RIGHT = 2STAGE_P = bound.BoundLineSymmetry([1, 4, 6, 10])(STAGE_LEFT3, STAGE_LEFT2, STAGE_LEFT1,STAGE_LEISURE,STAGE_RIGHT1, STAGE_RIGHT2, STAGE_RIGHT3) = (1, 2, 3,4,5, 6, 7)def __init__(self,  speedbound:boundlrtb.Boundlftb, speed=None, accelerate=None):super().__init__(speed, accelerate)self.speed_b = speedboundself.stage = self.STAGE_P.detect_section(self.speed[0])def w_acce(self):if self.speed_b.ylimit(self.speed[1]):if self.speed[1] > 0:self.setyAccelerate(-(self.ACCE_y + self.ACCE_F))else:self.setyAccelerate(-self.ACCE_y)def a_acce(self):if self.speed_b.xlimit(self.speed[0]):if self.speed[0] > 0:self.setxAccelerate(-(self.ACCE_x + self.ACCE_F))else:self.setxAccelerate(-self.ACCE_x)def s_acce(self):if self.speed_b.ylimit(self.speed[1]):if self.speed[1] < 0:self.setyAccelerate(self.ACCE_y + self.ACCE_F)else:self.setyAccelerate(self.ACCE_y)def d_acce(self):if self.speed_b.xlimit(self.speed[0]):if self.speed[0] < 0:self.setxAccelerate(self.ACCE_x + self.ACCE_F)else:self.setxAccelerate(self.ACCE_x)def drive(self):keys = pygame.key.get_pressed()if keys[K_w] and not keys[K_s]:self.w_acce()elif keys[K_s] and not keys[K_w]:self.s_acce()else:if self.accelerate[1]:self.accelerate[1] = 0if self.speed[1] > 0:self.speed[1] -= self.ACCE_Fif self.speed[1] < 0:self.speed[1] = 0elif self.speed[1] < 0:self.speed[1] += self.ACCE_Fif self.speed[1] > 0:self.speed[1] = 0if keys[K_a] and not keys[K_d]:self.a_acce()elif keys[K_d] and not keys[K_a]:self.d_acce()else:if self.accelerate[0]:self.accelerate[0] = 0if self.speed[0] > 0:self.speed[0] -= self.ACCE_Fif self.speed[0] < 0:self.speed[0] = 0elif self.speed[0] < 0:self.speed[0] += self.ACCE_Fif self.speed[0] > 0:self.speed[0] = 0self.updatespeed()self.updatestage()def updatestage(self):self.stage = self.STAGE_P.detect_section(self.speed[0])def updatespeed(self):self.speed[0] += self.accelerate[0]self.speed[1] += self.accelerate[1]self.speed[0] = self.speed_b.bound_1.setin(self.speed[0])self.speed[1] = self.speed_b.bound_2.setin(self.speed[1])def copy(self):return Engine(self.speed_b, self.speed[:], self.accelerate[:])class Enemy_Engine(mymove.Mymove):
# 敌人的引擎def __init__(self):super().__init__()self.last_acce = pygame.time.get_ticks()self.acce_time = self.ACCE_TIMEself.sleep_time = self.SLEEP_TIMEself.sleeping = Falseself.acceing = Falsedef copy(self):return Enemy_Engine()class Sa_1_Engine(Enemy_Engine):ACCE_X = 1ACCE_Y = 0.1ACCE_F = 0.5ACCE_TIME = 300SLEEP_TIME = 100def drive(self):# 睡眠结束super().updatespeed()if not self.acceing and not self.sleeping:d = random.randint(1, 4)if d == 1:self.w_acce()if d == 2:self.a_acce()if d == 3:self.s_acce()if d == 4:self.d_acce()self.acceing = True# 加速中elif self.acceing and not self.sleeping:now = pygame.time.get_ticks()if now - self.last_acce >= self.ACCE_TIME:self.sleeping = Trueself.acceing = Falseself.accelerate = [0,0]self.last_acce = now# 睡眠中elif self.sleeping:if self.speed[0] > 0:self.speed[0] -= self.ACCE_Fif self.speed[0] < 0:self.speed[0] = 0elif self.speed[0] < 0:self.speed[0] += self.ACCE_Fif self.speed[0] > 0:self.speed[0] = 0if self.speed[1] > 0:self.speed[1] -= self.ACCE_Fif self.speed[1] < 0:self.speed[1] = 0elif self.speed[1] < 0:self.speed[1] += self.ACCE_Fif self.speed[1] > 0:self.speed[1] = 0now = pygame.time.get_ticks()if now - self.last_acce >= self.SLEEP_TIME:self.sleeping = Falseself.last_acce = nowdef w_acce(self):self.accelerate[1] = -self.ACCE_Ydef a_acce(self):self.accelerate[0] = -self.ACCE_Xdef s_acce(self):# can use to drive showself.accelerate[1] = self.ACCE_Ydef d_acce(self):self.accelerate[0] = self.ACCE_Xdef copy(self):return Sa_1_Engine()

这样,飞机就只有controlcenter属性和weapon属性了

7.敌人飞机生成

敌人飞机生成涉及到实例对象产生的问题,和炮弹生成一样,用一个群组Group类的子类封装敌人的每隔一段时间随机生成的逻辑。为保证每个敌人完全独立,为每个组件都增加了一个copy函数,使之在内存中复制,从而不相互干扰

8.生命值的计算和显示逻辑。

如果没有生命值外框,又怎么知道扣了多少生命值呢?于是我设计了HpFrameBar(继承自pygame.sprite.Group)来封装外框和实条。

用Hp类来封装数值的运算代码(很简单,只有加和减)

玩家生命值条和外框的显示位置可以硬编码在左下角,但敌人的生命显示只能随敌人位置变化。于是也增加了HpFrameBar于一个敌人实例的绑定函数configure,且随敌人位置移动而移动

由于篇幅限制,没有讨论子弹和飞机爆炸播放逻辑和音效播放逻辑的实现。

技术介绍完。

目前游戏没有实现的是游戏结束逻辑,更丰富的战斗体验以及游戏进度保存。因为最近要学JavaScript/HTML/CSS了,所以这个游戏做到这样能玩就收手了,各位还请海涵。

源代码:

链接: https://pan.baidu.com/s/1SwBsF-bjoBbHkN_LY4Ddqw

提取码: mnfc 

链接永远有效,请放心食用!

Pygame游戏飞机大战《星野守望》相关推荐

  1. pygame实现飞机大战游戏

    标题:pygame实现飞机大战游戏 源码链接:我的github地址 一.具体演示 1.怪兽分为小怪,和大怪:大怪可以发射子弹 2.英雄飞机共有10个生命值 3.英雄飞机可以上下左右移动 4.显示了英雄 ...

  2. 体感游戏 | 手势识别玩飞机大战游戏(一) 用pygame实现飞机大战小游戏

    Color Space OpenCV与AI深度学习 后面将分四篇文章来介绍实现手势识别控制飞机大战游戏的功能,它们分别是: 使用Pygame实现简易飞机大战小游戏 使用Python+OpenCV实现简 ...

  3. Python游戏之Pygame——太空飞机大战(三)

    上一篇(Python游戏之Pygame--太空飞机大战(二))完成了敌机类以及敌机坠毁时释放包裹类,这一篇将给出英雄战机类和处理.由于英雄战机是由游戏者操控的,所以要处理操控事件,比如往那个方向飞,发 ...

  4. c 语言500行小游戏代码,500行代码使用python写个微信小游戏飞机大战游戏.pdf

    500行行代代码码使使用用python写写个个微微信信小小游游戏戏飞飞机机大大战战游游戏戏 这篇文章主要介绍了500行代码使用python写个微信小游戏飞机大战游戏,本文通过实例代码给大家介绍的非常详 ...

  5. Python游戏之Pygame——太空飞机大战(四)

    上一篇(Python游戏之Pygame--太空飞机大战(三))完成了英雄战机和星空,那么基本上飞机大战的主要元素都已经完成,该是总结成功玩自己游戏的时候了. 哦,差点忘了,Bullet类对于普通子弹和 ...

  6. Python游戏之Pygame——太空飞机大战(二)

    上一篇(Python游戏之Pygame--太空飞机大战(一))文章简单对游戏进行了说明,给出了部分配置文件以及子弹类.下面给出敌机类和方法. 大家直到,飞机必须能非,最好能非直线飞行.因此必须有X_s ...

  7. 【Python】Python小游戏--飞机大战

    一.前言 今天已经初四,舒服的在家躺尸的春节也算过去了,又要开始辛勤的(苦逼的)学习和工作了.说点题外话,今年春节的病毒疫情真的弄的人心惶惶,我也在这为国家和武汉加油,也向一线工作人员致敬,希望早日结 ...

  8. 用JAVA制作小游戏——飞机大战(三)

    本篇博客是对飞机大战游戏项目完整代码的展示 详细代码讲解: 用JAVA制作小游戏--飞机大战(一) 用JAVA制作小游戏--飞机大战(二) 最下方附整个程序的文件下载链接 代码展示 主界面 impor ...

  9. 用JAVA制作小游戏——飞机大战(二)

    本篇博客是对飞机大战游戏使用代码的展示 重难点: 首先需要鼠标能够控制战机,使鼠标在窗口内时始终能够使战机的位置与鼠标相同,实现鼠标控制战斗机移动. 其次需要能够以一定的速度产生子弹和敌机,并且以一定 ...

最新文章

  1. cp 过程流程图模板_19张必备流程图,收藏
  2. expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.spring
  3. 三维空间长度温度数量_罗斯蒙特644温度变送器怎样接线?
  4. 【数字信号处理】相关系数 ( 相关系数特点 | 完全相关 | 完全无关 | 部分相关 | 取值范围 | 相关信号产生 | 相干信号产生 )
  5. android点赞webview页面,Android WebView
  6. 【PAT乙级】1071 小赌怡情 (15 分)
  7. 腾讯视频怎么开启禁止界面硬件加速
  8. mysql8无法修改端口_mysql8.0.18 修改端口报错 Can't start server: Bind on TCP/IP port: Permission denied...
  9. [InnoDB系列] - InnoDB释放表空间
  10. java-RGB与十六进制的互相转换
  11. PHP给微信二维码 添加背景和昵称 ,微信带参数海报跨坑记录。
  12. linux系统如何安装mtk驱动程序,模块编译问题 给MTK芯片的wifi网卡编译linux驱动 系统是mint...
  13. 计算机配置中什么表示硬盘,电脑硬盘的分类介绍 硬盘中的Master和Slave代表什么意思...
  14. 关于amazon亚马逊SP-API申请注册,amazon亚马逊SPAPI开发人员资料注册,amazon亚马逊Selling Partner API申请注册详细指导
  15. 山东省2020年12月计算机考试,12月20日开始报名!山东2020年3月全国计算机等级考试注意事项来咯...
  16. sharepoint 2010 如何给讨论板(Discussion)话题添加回复(Reply)信息(Message)
  17. python学习实验报告(第十周)
  18. 我的嵌入式linux开发步骤
  19. Xcode的几个编译设置
  20. x200装linux驱动下载,Thinkpad X200 老机装WIN8.1 X64显卡驱动

热门文章

  1. 我用 Python 处理3万多条数据,只要几秒钟……
  2. Github上有趣的100个python项目
  3. 服务器维护是否属于现代服务业,​交通运输业是否属于现代服务业
  4. DVWA指点迷津-CSP Bypass
  5. Warning C206
  6. CoinOPS Next 街机掌机模拟器整合前端:自定义配置菜单和自定义界面功能介绍
  7. 淘宝双11数据分析与预测课程案例:实验环境搭配
  8. React Native资源汇总
  9. C语言读取JSON文件
  10. 【无标题】新冠病毒变异株检测——荧光定量PCR检测技术开发