14
2024
11

python编程学习-cat-rolling

学习python编程,在新东方少儿编程官网的自由创作平台做的一些作品。

可以在线运行,效果如下(在新页面中打开链接):

代码如下(用到平台自定义的xdf库):

from xdf import *
import math
W = 768
H = 1024
G = 0.85
JUMPF = -16
SPEED = 0.18
fill("cat-r-bg@004G")
setFrameRate(40)
levels = [
    ["w",150,201,"d",96,914,"c",102,135,"s",706,70,"k",342,933,"w",604,455,"s",362,389,"s",553,924,"w",177,715,"w",384,994],
    ["w",140,206,"d",351,914,"c",115,140,"s",650,210,"k",541,933,"w",730,475,"s",60,662,"s",79,933,"w",122,734,"w",384,994],
    ["w",584,155,"b",100,155,"d",337,914,"c",70,88,"s",67,631,"k",696,355,"w",-144,414,"s",686,525,"s",98,931,"w",206,697,"w",384,994,"w",824,414,"e",340,414],
    ["w",184,166,"b",668,166,"d",175,915,"c",48,95,"s",519,434,"k",48,229,"w",-149,520,"s",450,927,"s",86,721,"w",220,785,"w",384,994,"w",819,520,"e",335,520],
    ["w",-15,204,"b",265,710,"a",626,617,"d",139,915,"c",102,135,"s",702,139,"k",728,452,"w",924,204,"s",90,642,"s",273,930,"w",-219,710,"w",384,994,"w",1021,511,"w",749,710],
    ["w",174,170,"b",390,637,"a",537,901,"d",689,915,"c",43,100,"s",606,376,"k",713,576,"w",945,439,"s",651,743,"s",50,935,"w",-94,637,"w",384,994,"w",874,637],
    ["w",-114,165,"e",370,165,"a",410,550,"d",690,915,"c",49,94,"s",701,98,"k",717,403,"w",854,165,"s",47,576,"s",616,867,"w",948,465,"w",384,994,"a",587,546,"w",-79,640,"w",889,640,"b",405,640],
    ["w",0,187,"a",69,901,"d",80,534,"c",50,117,"s",393,537,"k",712,926,"f",768,187,"w",978,616,"s",694,546,"s",83,761,"w",-213,614,"w",384,994,"w",-166,824,"w",973,824],
    ["w",-41,201,"f",928,666,"d",97,393,"c",54,135,"s",303,376,"k",85,924,"w",-28,473,"s",61,729,"s",657,917,"w",-25,798,"w",384,994],
    ["w",50,200,"a",503,102,"d",297,611,"c",67,129,"s",296,481,"k",393,938,"f",818,200,"w",600,691,"s",124,570,"s",702,859,"w",384,994],
    ["a",687,365,"d",530,914,"c",102,130,"s",63,269,"k",66,933,"f",384,200,"s",44,697,"s",529,833,"w",384,994,"f",384,460,"h",384,755,"a",383,904],
    ["w",115,185,"a",315,647,"d",96,667,"c",67,118,"s",342,386,"k",591,930,"f",2,743,"s",587,716,"s",74,924,"w",384,994,"f",4,460,"f",883,185]
]

def checkHitRectCircle(dx, dy, w, h, r):
    if dy < h and dx < r + w:
        return True
    if dx < w and dy < r + h:
        return True
    if dx > w and dy > h and dx < w + r and dy < h + r and dx * dx + dy * dy < r * r:
        return True
    return False
class Sprite:
    def __init__(self, src, x = 0, y = 0, size = None, name = ''):
        self.stamp = stamp(src, x, y, size)
        self.src = src
        self.name = name
        self.x = x
        self.y = y
        self.speedY = 0
        self.visible = True
        self.onClick = None
        self.removed = False
        self.bd = None
        self.isStand = False
        pass
    def change(self, src):
        self.src = src
        self.stamp.change(src)
    def reset(self):
        pass
    def front(self):
        self.stamp.front()
        pass
    def update(self):
        pass
    def refresh(self, parent):
        if self.removed:
            if not self.stamp.hidden:
                self.stamp.hide()
            return
        if self.visible and parent.visible:
            if self.stamp.hidden:
                self.stamp.show()
        else:
            if not self.stamp.hidden:
                self.stamp.hide()
        if not self.stamp.hidden:
            self.stamp.move(parent.x + self.x, parent.y + self.y)
        pass
    def tap(self):
        if self.visible and self.stamp.hits(x, y):
            if self.onClick:
                self.onClick()
            return True
        return False
    pass

class Layer:
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y
        self.children = []
        self.pool = []
        self.visible = True
        pass
    def addSp(self, src, x = 0, y = 0, size = None, name = ''):
        for sp in self.pool:
            if sp.src == src:
                self.pool.remove(sp)
                self.children.append(sp)
                sp.x = x
                sp.y = y
                sp.name = name
                if sp.src != src:
                    sp.stamp.change(src)
                # todo size
                sp.removed = False
                sp.visible = True
                sp.speedY = 0
                sp.front()
                return sp
        sp = Sprite(src, x, y, size, name)
        self.children.append(sp)
        return sp
    def clear(self):
        self.pool.extend(self.children)
        self.children.clear()
        pass
    def removeSp(self, sp):
        self.pool.append(sp)
        self.children.remove(sp)
        sp.removed = True
    def update(self):
        pass
    def refresh(self):
        for sp in self.children:
            sp.refresh(self)
        for sp in self.pool:
            sp.removed = True
            sp.refresh(self)
        pass
    def tap(self):
        if self.visible:
            for sp in reversed(self.children):
                if sp.visible and sp.tap():
                    return True
        return False
    pass

class Home(Layer):
    def __init__(self):
        Layer.__init__(self, W / 2, H / 2)
        self.addSp("car-r-name@004B", 0, -150)
        self.addSp("cat-r-cat@003v", 0, 0)
        self.addSp("cat-r-stt@004F", 0, 150)
        pass
    def tap(self):
        if abs(x - self.x) < 138 and abs(y - self.y - 150) < 61:
            game.showMenu()
            self.visible = False
            return True
        return False
    pass
class LevelSelectMenu(Layer):
    def __init__(self):
        Layer.__init__(self, W / 2, H / 2)
        self.bg = self.addSp("cat-r-menu@0049", 0, 0)
        self.locks = []
        self.stars = []
        for j in range(3):
            for i in range(4):
                self.locks.append(self.addSp("cat-r-lock@004A", -118+19 + i * 66, -52+19+50*j))
                for k in range(3):
                    self.stars.append(self.addSp("cat-r-star@004C", -118+19 + i * 66 + 12 * k - 12, -52+19+50*j+13, 12))
        pass
    def updateRecords(self, records):
        for sp in self.locks:
            sp.visible = True
        for sp in self.stars:
            sp.visible = False
        b = True
        for i in range(12):
            self.locks[i].visible = not b
            if records[i] == 0:
                b = False
            for j in range(3):
                if j < records[i]:
                    self.stars[i * 3 + j].visible = True
        pass
    def update(self):
        super().update()
        pass
    def refresh(self):
        super().refresh()
        pass
    def tap(self):
        for i in range(len(self.locks)):
            sp = self.locks[i]
            if not sp.visible:
                x0 = x - self.x - sp.x
                y0 = y - self.y - sp.y
                if abs(x0) < 19 and abs(y0) < 19:
                    #print(i, sp.src[7:], x0//1, y0//1)
                    game.startLevel(i)
                    self.visible = False
                    return True
            else:
                break
        pass
    pass

class Gamelayer(Layer):
    def __init__(self):
        Layer.__init__(self)
        self.pool = []
        self.cat = None
        self.grayCat = None
        self.door = None
        self.starNum = 0
        self.count = 0
        self.hasKey = False
        self.state = 0
        pass
    def tap(self):
        if self.state != 0:
            return False
        for sp in self.children:
            if not sp.visible:
                continue
            dx = x - sp.x
            dy = y - sp.y
            if sp.name == 'r':
                if abs(dx) < 50 and abs(dy) < 50:
                    game.restart()
                    return True
            elif sp.name == 'm':
                if abs(dx) < 50 and abs(dy) < 50:
                    game.backToMenu()
                    return True
                pass
            elif sp.name == 'c':
                if dx * dx + dy * dy < (36+10) * (36+10):
                    if self.grayCat == None and (abs(self.cat.x - self.cat.ox) > 36 or abs(self.cat.y - self.cat.oy) > 36):
                        self.grayCat = self.addSp("cat-r-catg@003w", self.cat.x, self.cat.y, None, "g")
                        self.cat.x = self.cat.ox
                        self.cat.y = self.cat.oy
                        self.cat.speed = self.cat.ospeed
                        self.cat.speedY = 0
                    return True
            elif sp.name == 'b':
                if abs(dx) < 100 and abs(dy) < 30:
                    sp.name = "e"
                    sp.change("cat-r-wd4@004g")
                    return True
                pass
            elif sp.name == 'e':
                if abs(dx) < 100 and abs(dy) < 30:
                    sp.name = "b"
                    sp.change("cat-r-wd3@004f")
                    return True
                pass
            elif sp.name == 'f':
                if abs(dx) < 384 and abs(dy) < 30:
                    sp.name = "h"
                    sp.change("cat-r-wd6@004i")
                    return True
                pass
            elif sp.name == 'h':
                if abs(dx) < 384 and abs(dy) < 30:
                    sp.name = "f"
                    sp.change("cat-r-wd5@004h")
                    return True
                pass
            elif sp.name == 'g':
                if dx * dx + dy * dy < 36 * 36:
                    self.grayCat = None
                    self.removeSp(sp)
                    return True
                pass
        self.jumpCat()
        return False
    def jumpCat(self):
        if not self.cat.isStand:
            return
        self.cat.speedY = JUMPF
        self.cat.isStand = False
    def moveCrab(self):
        for sp in self.children:
            if not sp.visible:
                continue
            if sp.name == 'd' or sp.name == 'a':
                sp.speedY += G
                sp.y += sp.speedY
                sz = 66 if sp.name == 'a' else 56
                if self.hitFloor(sp, sz, sz):
                    sp.y -= sp.speedY
                    sp.speedY = 0
                    sp.isStand = True
        pass
    def hitFloor(self, sp0, w, h):
        for sp in self.children:
            dx = sp.x - sp0.x
            dy = sp.y - sp0.y
            if sp.name == 'w':
                if abs(dx) < (w + 384) and abs(dy) < (h + 30):
                    return True
            if sp.name == 'b':
                if abs(dx) < (w + 100) and abs(dy) < (h + 30):
                    return True
            if sp.name == 'f':
                if abs(dx) < (w + 384) and abs(dy) < (h + 30):
                    return True
            if sp.name == 'g':
                if abs(dx) < (w + 36) and abs(dy) < (h + 36):
                    return True
        return False
    def moveCat(self):
        cat = self.cat
        # rotate
        cat.rotation += cat.speed
        cat.stamp.rotate(cat.rotation * 180 / 3.141592653)
        # move x
        cat.speedX = cat.speed * 36
        cat.x += cat.speedX
        if self.checkCatHitFloor():
            cat.x -= cat.speedX
            cat.speed = -cat.speed
        if cat.x >= 768 - 36 and cat.speed > 0:
            cat.x = 768 - 36
            cat.speed = -cat.speed
        elif cat.x < 36  and cat.speed < 0:
            cat.x = 36
            cat.speed = -cat.speed
        # move y
        cat.speedY += G
        cat.y += cat.speedY
        cat.isStand = False
        if self.checkCatHitFloor():
            cat.y -= cat.speedY
            cat.speedY = 0
            cat.isStand = True
        pass
    def checkCatHitFloor(self):
        cat = self.cat
        for sp in self.children:
            dx = sp.x - cat.x
            dy = sp.y - cat.y
            if sp.name == 'w':
                if abs(dx) < (36 + 384) and abs(dy) < (36 + 30):
                    return True
            if sp.name == 'b':
                if abs(dx) < (36 + 100) and abs(dy) < (36 + 30):
                    return True
            if sp.name == 'f':
                if abs(dx) < (36 + 384) and abs(dy) < (36 + 30):
                    return True
            if sp.name == 'g':
                if abs(dx) < (36 + 36) and abs(dy) < (36 + 36):
                    return True
        return False
    
    def checkCatHit(self):
        # check clission
        cat = self.cat
        for sp in self.children:
            if not sp.visible:
                continue
            dx = sp.x - cat.x
            dy = sp.y - cat.y - cat.speedY
            sd = dx * dx + dy * dy
            if sp.name == 'd': #门
                if self.hasKey and sd < (36 + 56 - 10) * (36 + 56 - 10):
                    self.complete(sp)
            elif sp.name == 'k': #钥匙
                if sd < (36 + 29) * (36 + 29):
                    sp.visible = False
                    self.hasKey = True
            elif sp.name == 's': #星星
                if sd < (36 + 29) * (36 + 29):
                    sp.visible = False
                    self.starNum += 1
            elif sp.name == 'a': #螃蟹
                if sd < (36 + 66) * (36 + 66):
                    self.fail()
            pass
            #print(sp.name)
        pass
    def update(self):
        super().update()
        if not self.cat:
            return
        if self.state == 0:
            self.moveCat()
            self.moveCrab()
            self.checkCatHit()
        elif self.state == 1:
            self.count += 1
            if self.count == 8:
                game.complete(self.starNum)
        elif self.state == 2:
            self.count += 1
            if self.count == 10:
                game.gameOver()
        elif self.state == 3:
            self.count += 1
            if self.count == 20:
                self.state = 0
                self.count = 0
        pass
    def fail(self):
        self.state = 2
    def complete(self, door):
        self.state = 1
        self.openDoor()
        pass
    def refresh(self):
        super().refresh()
        pass
    def start(self, arr):
        self.initLevel(arr)
        self.visible = True
        pass
    def openDoor(self):
        self.door.change("cat-r-door@004M")
        pass
    def initLevel(self, arr):
        self.cat = None
        self.door = None
        self.grayCat = None
        self.starNum = 0
        self.count = 0
        self.hasKey = False
        self.state = 3
        self.clear()
        for i in range(0, len(arr), 3):
            s = arr[i]
            x = arr[i+1]
            y = arr[i+2]
            if s == 'w':
                self.addSp("cat-r-w1@004I", x, y, None, s)
            elif s == 'd':
                self.door = self.addSp("cat-r-dor1@004N", x, y, None, s)
            elif s =='c':
                self.cat = self.addSp("cat-r-cat@003v", x, y, None, s)
                self.cat.speed = SPEED
                self.cat.speedX = self.cat.speed * 36
                self.cat.rotation = 0
                self.cat.speedY = 0
                self.cat.ox = self.cat.x
                self.cat.oy = self.cat.y
                self.cat.ospeed = self.cat.speed
            elif s =='s':
                self.addSp("cat-r-star@004C", x, y, None, s)
            elif s =='k':
                self.addSp("cat-r-key@003z", x, y, None, s)
            elif s =='a':
                self.addSp("cat-r-crab@0046", x, y, None, s)
            elif s =='b':
                self.addSp("cat-r-wd3@004f", x, y, None, s)
            elif s =='e':
                self.addSp("cat-r-wd4@004g", x, y, None, s)
            elif s =='f':
                self.addSp("cat-r-wd5@004h", x, y, None, s)
            elif s =='h':
                self.addSp("cat-r-wd6@004i", x, y, None, s)
        self.addSp("cat-r-menu@003s", 50, 50, None, "m")
        self.addSp("cat-r-rst@003t", 150, 50, None, "r")
        self.cat.front()
        pass
    pass

class CompleteLayer(Layer):
    def __init__(self):
        Layer.__init__(self, W / 2, H / 2)
        self.addSp("cat-r-comp@003x", 0, 0)
        self.stars = [
            self.addSp("cat-r-star@004C", -52, -38, 40),
            self.addSp("cat-r-star@004C", -3, -54, 60),
            self.addSp("cat-r-star@004C", 46, -38, 40)
        ]
        pass
    def setStar(self, num):
        for st in self.stars:
            st.visible = False
        for i in range(num):
            self.stars[i].visible = True
        pass
    def update(self):
        super().update()
        pass
    def refresh(self):
        super().refresh()
        pass
    def tap(self):
        rects = [[-51, 103, 48], [-3, 103, 48], [45, 103, 48]]
        for rect in rects:
            x0 = x - self.x - (-51)
            y0 = y - self.y - 103
            i = int((x0 + 24) / 48)
            if abs(y0) < 24 and i >= 0 and i <= 2:
                self.visible = False
                if i == 0:
                    game.goHome()
                elif i == 1:
                    game.backToMenu()
                elif i == 2:
                    game.nextLevel()
                return True
        return False
    pass


class Game:
    def __init__(self):
        self.homeLayer = Home()
        self.menuLayer = LevelSelectMenu()
        self.gameLayer = Gamelayer()
        self.compLayer = CompleteLayer()
        self.layers = [self.homeLayer, self.menuLayer, self.gameLayer, self.compLayer]
        #self.records = [1,1,1,1,1,1,1,1,1,1,1,1]
        self.records = [0,0,0,0,0,0,0,0,0,0,0,0]
        self.level = 0
        self.hideAll()
        self.homeLayer.visible = True
        pass
    def hideAll(self):
        for layer in self.layers:
            layer.visible = False
        pass
    def update(self):
        for layer in self.layers:
            layer.update()
        pass
    def refresh(self):
        for layer in self.layers:
            layer.refresh()
        pass
    def tap(self):
        for layer in self.layers:
            if layer.visible and layer.tap():
                break
        pass
    def complete(self, keyNum):
        self.records[self.level] = keyNum
        self.hideAll()
        self.compLayer.setStar(keyNum)
        self.compLayer.visible = True
        pass
    def showMenu(self):
        self.hideAll()
        self.menuLayer.updateRecords(self.records)
        self.menuLayer.visible = True
        pass
    def gameOver(self):
        self.restart()
        pass
    def startLevel(self, level):
        self.level = level
        self.start()
        pass
    def goHome(self):
        self.hideAll()
        self.homeLayer.visible = True
        pass
    def backToMenu(self):
        self.hideAll()
        self.menuLayer.updateRecords(self.records)
        self.menuLayer.visible = True
        pass
    def nextLevel(self):
        if self.level < 11:
            self.level += 1
        self.start()
        pass
    def start(self):
        self.hideAll()
        self.gameLayer.visible = True
        self.gameLayer.start(levels[self.level])
        pass
    def restart(self):
        self.start()
        pass
    pass

game = Game()

def tap():
    game.tap()
    pass

def loop():
    game.update()
    game.refresh()
    pass

















也可以下载代码,本地python环境运行(用pygame封装了xdf库)。



« 上一篇下一篇 »

相关文章:

python编程学习-华容道  (2024-11-14 16:43:25)

python编程学习-动画  (2024-11-14 16:39:37)

python编程学习-别踩白块  (2024-11-14 16:38:59)

python编程学习-俄罗斯方块  (2024-11-14 16:38:19)

python编程学习-井字棋  (2024-11-14 16:34:9)

python编程学习-五子棋  (2024-11-14 16:33:23)

python编程学习-乒乓  (2024-11-14 16:32:46)

python编程学习-一笔画关卡生成  (2024-11-14 16:32:6)

python编程学习-一笔画  (2024-11-14 16:31:27)

python编程学习-woblox  (2024-11-14 16:30:47)

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。