学习python编程,在新东方少儿编程官网的自由创作平台做的一些作品。
可以在线运行,效果如下(在新页面中打开链接):
代码如下(用到平台自定义的xdf库):
from xdf import * import math TIME_SCALE = 1.5 GROUND_Y = 800 SCREEN_W = 768 SCREEN_H = 1024 GRAVITY = 1.0 * TIME_SCALE AREA_RECT = "rect" AREA_CIRCLE = "circle" def rad2ang(rad): return 180 * rad / math.pi def ang2rad(ang): return math.pi * ang / 180 class Mario: def __init__(self, positionX, positionY): self.g = GRAVITY self.groundY = GROUND_Y self.positionX = positionX self.positionY = positionY self.x = 0 self.y = 0 self.vx = 0 self.vy = 0 self.maxV = 6 * TIME_SCALE self.jumpForce = 20.0 * TIME_SCALE self.ax = 1.0 * TIME_SCALE self.ux = 0.05 self.uy = 0.05 self.key = {} self.isDie = False self.godMode = False self.bulletMode = False self.clearanceMode = False self.width = 32 self.height = 54 self.currentFrame = 0 self.scaleX = 1 self.isPlaying = True self.starCount = 0 self.hitArea = [ AREA_RECT, self.x - self.width / 2, self.y - self.height, self.width, self.height ] # self.frames = ["mario001@001n", "mario002@001o", "mario003@001m", "mario002@001o", "mario004@001t"] self.totalFrames = len(self.frames) self.sp = stamp(self.frames[0]) self.sp.size(self.height) # self.lastFrame = 0 self.lastScaleX = 1 # self.reset() pass def updateHitArea(self): self.hitArea[1] = self.x - self.width / 2 self.hitArea[2] = self.y - self.height pass def reset(self): self.starCount = 0 self.isDie = False self.godMode = False self.scaleX = 1 self.x = self.positionX self.y = self.positionY self.gotoAndStop(0) pass def refresh(self): if self.isPlaying: self.currentFrame += 1 if self.currentFrame == self.totalFrames: self.currentFrame = 0 elif self.currentFrame == 4: self.currentFrame = 0 if self.lastScaleX != self.scaleX: self.lastScaleX = self.scaleX self.sp.flip() if self.lastFrame != self.currentFrame: self.lastFrame = self.currentFrame self.sp.change(self.frames[self.currentFrame]) self.sp.move(self.x, self.y - self.height / 2) self.sp.front() if self.starCount > 0: self.starCount -= 1 if self.starCount % 5 == 3: self.sp.hide() else: self.sp.show() if self.starCount == 0: self.godMode = False pass def gotoAndStop(self, frame): self.currentFrame = frame self.isPlaying = False pass def play(self): self.isPlaying = True pass def keyDown(self, code, key): self.key[code] = True pass def keyUp(self, code, key): self.key[code] = False pass def update(self): if self.isDie: if self.y > 100: self.y -= 50 else: self.move() pass def move(self): self.checkKey() # 更新速度 if abs(self.vx) < 1: self.vx = 0 else: self.vx -= self.vx * self.ux if self.y + self.vy + self.g - self.vy * self.uy > self.groundY: self.y = self.groundY self.vy = 0 else: self.vy += self.g - self.vy * self.uy # 更新位置 if self.x + self.vx > 0 and self.x + self.vx < 768: self.x += self.vx self.y += self.vy # 人物的动画效果 if self.y < self.groundY: self.gotoAndStop(2) elif self.vx != 0: if self.vx < 0: self.scaleX = -1 else: self.scaleX = 1 self.play() else: if self.currentFrame == 2: self.gotoAndStop(0) pass def checkKey(self): for i in self.key: if self.key[i]: if i == 39: if self.vx < self.maxV: self.vx += self.ax elif i == 37: if self.vx > -self.maxV: self.vx -= self.ax elif i == 38: if self.y == self.groundY: self.vy = -self.jumpForce * (1 + self.vx * self.vx * 0.003) pass def die(self): self.isDie = True self.gotoAndStop(4) pass def setGodMode(self, mode): self.godMode = mode self.starCount = 100 pass pass class Ball: def __init__(self): self.groundY = GROUND_Y self.g = GRAVITY self.x = 0 self.y = 0 self.vx = 0 self.vy = 0 self.r = 30 self.rotation = 0 self.isDie = False self.color = "red" self.score = 1 self.moveMode = Ball.RIGHT2LEFT self.ballMode = Ball.NORMAL self.jumpMode = Ball.HAVELOSS self.hitArea = [ AREA_CIRCLE, self.x, self.y, self.r ] # self.circle = circle(0, 0, self.r, self.color) self.sp = stamp("face001@001r") # self.reset() pass def updateHitArea(self): self.hitArea[1] = self.x self.hitArea[2] = self.y self.hitArea[3] = self.r pass def reset(self): self.score = 1 self.isDie = False self.moveMode = Ball.RIGHT2LEFT self.ballMode = Ball.NORMAL self.vx = (-random(300) / 100 - 3) * TIME_SCALE self.vy = 0 self.x = SCREEN_W + self.r self.y = self.groundY - 180 - random(self.r * 2) a = random(len(Ball.COLORS))-1 self.color = Ball.COLORS[a] self.circle.change(self.color) if random(100) > 95: self.setBallMode(Ball.BIG) self.setMoveMode(Ball.LEFT2RIGHT) pass def update(self): self.rolling() self.x += self.vx if self.jumpMode == Ball.HAVELOSS: self.vy += self.g self.y += self.vy else: self.y += self.vy self.vy += self.g pass if self.y >= self.groundY - self.r: self.y = self.groundY - self.r self.vy *= -1 if self.x < -self.r * 2 - 10 or self.x > SCREEN_W + self.r * 2: self.die() pass pass def refresh(self): self.sp.size(self.r) self.sp.move(self.x, self.y) self.sp.rotate(self.rotation) self.circle.size(self.r) self.circle.move(self.x, self.y) if self.isDie: self.sp.hide() self.circle.hide() else: self.sp.show() self.circle.show() pass def die(self): self.isDie = True pass def rolling(self): self.rotation += rad2ang(self.vx / self.r) pass def setMoveMode(self, dr): if dr == Ball.LEFT2RIGHT: self.moveMode = Ball.LEFT2RIGHT self.x = -self.r self.vx = -self.vx pass def setBallMode(self, mode): if mode == Ball.BIG: self.score = 2 self.ballMode = Ball.BIG self.r = 90 self.y = self.groundY - self.r pass pass Ball.COLORS = ["red", "green", "blue", "yellow", "aqua", "fuchsia"] Ball.RIGHT2LEFT = 1 Ball.LEFT2RIGHT = -1 Ball.NORMAL = "normal" Ball.BIG = "big" Ball.HAVELOSS = "haveLoss" Ball.NOLOSS = "noLoss" class Star: def __init__(self): self.groundY = GROUND_Y self.g = GRAVITY self.x = 0 self.y = 0 self.vx = 0 self.vy = 0 self.r = 25 self.rotation = 0 self.isDie = False self.starCount = 0 self.score = 2 self.hitArea = [ AREA_CIRCLE, self.x, self.y, self.r ] # self.sp = stamp("star001@001p") # self.reset() pass def updateHitArea(self): self.hitArea[1] = self.x self.hitArea[2] = self.y self.hitArea[3] = self.r pass def reset(self): self.isDie = False self.starCount = 0 self.vx = (-random(300) / 100 - 3) * TIME_SCALE self.vy = 0 self.x = SCREEN_W + self.r self.y = self.groundY - random(self.r * 2) - 180 pass def update(self): self.rolling() self.x += self.vx self.vy += self.g self.y += self.vy if self.y >= self.groundY - self.r: self.y = self.groundY - self.r self.vy *= -1 if self.x < -self.r * 2 - 10 or self.x > SCREEN_W + self.r * 2: self.die() pass pass def refresh(self): self.sp.size(self.r * 2) self.sp.move(self.x, self.y) self.sp.rotate(self.rotation) self.starCount += 1 if self.isDie or self.starCount % 5 == 0: self.sp.hide() else: self.sp.show() pass def die(self): self.isDie = True pass def rolling(self): self.rotation += rad2ang(self.vx / self.r) pass pass class Mushroom: def __init__(self, name = "mogu001@001s", size = 50): self.vx = 0 self.score = 1 self.x = 0 self.y = 0 self.isDie = False self.height = self.width = size self.hitArea = [ AREA_RECT, self.x - self.width / 2, self.y - self.height, self.width, self.height ] # self.sp = stamp(name) self.sp.size(self.width) # self.reset() pass def updateHitArea(self): self.hitArea[1] = self.x - self.width / 2 self.hitArea[2] = self.y - self.height pass def reset(self): self.isDie = False self.vx = (random(300) / 100 - 5) * TIME_SCALE self.x = SCREEN_W self.y = GROUND_Y pass def refresh(self): self.sp.move(self.x, self.y - self.height / 2) if self.isDie: self.sp.hide() else: self.sp.show() pass def update(self): self.x += self.vx if self.x < -20: self.die() pass def die(self): self.isDie =True pass pass def getSp(Cla): for sp in spPool: if isinstance(sp, Cla): spPool.remove(sp) sp.reset() return sp return Cla() def addMc(Cla): mc = getSp(Cla) addChild(mc) pass def addChild(sp): spArr.append(sp) def hitRectCircle(rec, cir): rec2 = [ rec[0] + rec[2] / 2 - cir[0], rec[1] + rec[3] / 2 - cir[1], cir[2] + rec[2] / 2, cir[2] + rec[3] / 2 ] if rec2[0] <= rec2[2] and rec2[0] >= -rec2[2] and rec2[1] <= rec2[3] and rec2[1] >= -rec2[3]: return True dx = min(abs(cir[0] - rec[0]), abs(cir[0] - rec[0] - rec[2])) dy = min(abs(cir[1] - rec[1]), abs(cir[1] - rec[1] - rec[3])) return dx * dx + dy * dy <= cir[2] * cir[2] def hitRectRect(rec1, rec2): return rec1[0] <= rec2[0] + rec2[2] and rec1[0] + rec1[2] >= rec2[0] and rec1[1] <= rec2[1] + rec2[3] and rec1[1] + rec1[3] >= rec2[1] def checkHit(area0, area1): if area0[0] == AREA_RECT and area1[0] == AREA_CIRCLE: return hitRectCircle(area0[1:], area1[1:]) if area0[0] == AREA_CIRCLE and area1[0] == AREA_RECT: return hitRectCircle(area1[1:], area0[1:]) if area0[0] == AREA_RECT and area1[0] == AREA_RECT: return hitRectRect(area0[1:], area1[1:]) return False def checkCollision(): global score for sp in spArr: sp.updateHitArea() for sp in spArr: if not mario.isDie and not sp.isDie and sp != mario: if checkHit(mario.hitArea, sp.hitArea): sp.die() score += sp.score if isinstance(sp, Ball): if not mario.godMode: mario.die() elif isinstance(sp, Mushroom): pass elif isinstance(sp, Star): mario.setGodMode(True) pass pass pass def addMcs(): global N N += 1 if N % 60 == 0: addMc(Ball) if N % 100 == 0: addMc(Mushroom) if N % 200 == 0: addMc(Star) pass def removeDie(): i = len(spArr) - 1 while i >= 0: sp = spArr[i] if sp.isDie and not isinstance(sp, Mario): spPool.append(sp) spArr.pop(i) i -= 1 def reset(): global score, N N = 0 score = 0 gameOverTf.hide() for sp in spArr: sp.die() mario.reset() pass def keydown(code, key): mario.keyDown(code, key) pass def keyup(code, key): mario.keyUp(code, key) pass def tap(): if mario.isDie: reset() def loop(): for sp in spArr: sp.update() # if not mario.isDie: addMcs() checkCollision() gameOverTf.hide() else: gameOverTf.show() # for sp in spArr: sp.refresh() # removeDie() # global score scoreTf.change("得分:" + str(score)) pass ground = box(0, GROUND_Y, SCREEN_W, SCREEN_H - GROUND_Y, "blue") mario = Mario(200, 100) spArr = [mario] spPool = [] score = 0 scoreTf = text("得分:0", 0, 50, 50, "red") gameOverTf = text("Game Over", 100, "red", "center") N = 0
也可以下载代码,本地python环境运行(用pygame封装了xdf库)。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。