用pygame制作小宝贝的算术练习游戏

in STEEM CN/中文3 years ago

动画.gif

一、游戏基本设想

上过一些像有道数学这些在线培训项目的体验课。对这些APP用游戏进行教学的思路非常的赞同。不过这些APP的订阅费用不菲,按年计都在数千元左右。而且最近新出台的课外培训监管政策,不知会不会有什么影响?所以预付款也有很大的风险。最关键的因素还是性价比太低了,因为小孩的启蒙课程难度都很低。如果懂编程的话,完全也可以自己动手来开发。

今天我做的这个是让小朋友练习10以内加法的小游戏。游戏的规则是。在屏幕上方给出题目,下面给出三个候选答案。小朋友可以通过箭头控制小人的移动,将小人移动到正确答案的数字下面。点击小人,如果答案正确。小人就会跳上数字方块的上面。如果答错了,小人就会落回地面。

二、pygame最小系统

因为前段时间学习了用派生语言的拍game模组进行游戏编程,所以这个游戏也是用拍game来编写,拍game编写游戏,有一个最小系统,可以显示一个全黑的屏幕,然后在此基础上不断的增加内容。

import pygame
pygame.init()
screen = pygame.display.set_mode((400,800))

running = True

while running:
    clock.tick(30)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    screen.fill((0,0,0))
    pygame.display.update()

三、精灵(sprite)系统

pygame模组中有一个精灵系统,可以非常方便的将游戏对象组织进不同的精灵主实现碰撞检测,图像刷新,图像取消显示等功能。
在这个游戏中我设置了玩家精灵。候选答案砖块精灵。题目栏精灵和控制键精灵。

四、源代码

# -*- coding: utf-8 -*-

import pygame
import random

gravity = 1.2
support = 0

pygame.init()
screen = pygame.display.set_mode((400,800))#,pygame.FULLSCREEN|pygame.SCALED)


background = pygame.image.load('image\Background.jpg')
background = pygame.transform.smoothscale(background,(400,800))


class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('image\player.jpg').convert()
        pygame.Surface.set_colorkey(self.image,(0,0,0))
        self.image = pygame.transform.smoothscale(self.image,(80,90))
        #  self.image = pygame.Surface((50,50))
        #  self.image.fill((0,255,0))
        self.rect=self.image.get_rect()
        self.rect.center =(200,700)
        self.vel_x = 0
        self.vel_y = 0
        self.jumping = False
        self.last_update = 0

    def update(self):
        global gravity
        global support
        self.vel_y += gravity+support
        self.rect=self.rect.move(self.vel_x,self.vel_y)
        if self.rect.right < 0:
            self.rect.left = 400

        if self.rect.left > 400:
            self.rect.right = 0

        if self.rect.bottom >= 725:
            self.rect.bottom =725
            support = -1*gravity
            self.jumping = False

        else:
            support = 0

        if support == 0:
            self.jumping = True


class brick(pygame.sprite.Sprite):
    def __init__(self,center_x,center_y,answer_number,idx):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((50,50))
        self.image.fill((255,0,0))
        self.rect=self.image.get_rect()
        self.rect.center =(center_x,center_y)
        self.font =  pygame.font.Font('segoeprb.ttf',32)
        self.answer_number = answer_number
        self.idx = idx

    def update(self):
        self.image.fill((255,0,0))
        choice_number = self.font.render(str(self.answer_number),True,(0,255,0))
        self.image.blit(choice_number,(5,-10))

class question_banner(pygame.sprite.Sprite):
    def __init__(self,center_x,center_y,question):
        pygame.sprite.Sprite.__init__(self)
        self.text = question
        self.font =  pygame.font.Font('segoeprb.ttf',64)
        self.image = pygame.Surface((300,80))
        self.image.fill((0,0,255))
        self.rect=self.image.get_rect()
        self.rect.center =(center_x,center_y)

    def update(self):
        question_img = self.font.render(self.text,True,(255,0,0))
        self.image.blit(question_img,(10,-10))


class contral(pygame.sprite.Sprite):
    def __init__(self,image,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load(image)
        self.image = pygame.transform.smoothscale(self.image,(60,40))
        self.rect = self.image.get_rect()
        self.rect.center = (x,y)
        
    def update(self):
        pass




adds_num=[1,1]
all_sprites= pygame.sprite.Group()
player = Player()
brick1  = brick(80,600,1,0)
brick2  = brick(200,600,2,1)
brick3  = brick(320,600,3,2)
QuestionBanner = question_banner(200,100,str(adds_num[0])+'+'+str(adds_num[1])+'=?') 
right_arrow = contral('image\Right.png',350,750)
left_arrow = contral('image\Left.png',50,750)
all_sprites.add(player,brick1,brick2,brick3,QuestionBanner,right_arrow,left_arrow)

bricks = pygame.sprite.Group()
bricks.add(brick1,brick2,brick3)
clock = pygame.time.Clock()


def update_question(pre_idx=1):
    answers=random.sample(range(1,11),3)
    brick1.answer_number=answers[0]
    brick2.answer_number=answers[1]
    brick3.answer_number=answers[2]
    idx=random.sample(range(0,3),1)[0]
    while idx == pre_idx:
        idx=random.sample(range(0,3),1)[0]
    adds_num[0]=random.randint(0,answers[idx])
    adds_num[1]=answers[idx]-adds_num[0]
    QuestionBanner.image.fill((0,0,255))
    QuestionBanner.text = str(adds_num[0])+'+'+str(adds_num[1])+'=?'  

running = True

while running:
    clock.tick(30)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        if event.type == pygame.MOUSEBUTTONDOWN and event.button ==1:
            if left_arrow.rect.collidepoint(event.pos):
                player.vel_x -= 5
            elif right_arrow.rect.collidepoint(event.pos):
                player.vel_x = 5

            if player.rect.collidepoint(event.pos):
                player.vel_y = -20
        elif event.type == pygame.MOUSEBUTTONUP:
            player.vel_x = 0

    #update
    all_sprites.update()
    hits = pygame.sprite.spritecollide(player,bricks,False)
    if not hits:
        ready2change_question = True
    if hits and player.vel_y > 0:
        player.last_update = pygame.time.get_ticks()
    if hits and player.vel_y >= 0: 
        if sum(adds_num)==hits[0].answer_number:
            player.vel_y = 0
            player.rect.bottom = hits[0].rect.top+1
            support = -1*gravity
            player.jumping = False
            now = pygame.time.get_ticks()
            if ready2change_question and now - player.last_update>3000:
                update_question(hits[0].idx)
                ready2change_question = False

    #render
    screen.blit(background,(0,0))
    all_sprites.draw(screen)


    pygame.display.update()

五、改进想法

游戏基本功能得以实现,不过缺乏游戏中的奖励和惩罚机制。我的想法是加入三个红星代表生命值,如果每答错一题就掉一个红星,同时加入记分,每答对一题就加一分。三条命都用完后记录最高分。通过这种办法激励小朋友。尽量准确的答题。并且挑战最高分数。

家里有小孩的网友,有什么好的创意。可以留言告知,如果有人有兴趣,达到一定完成度的时候,我会共享出来。

Coin Marketplace

STEEM 0.30
TRX 0.12
JST 0.033
BTC 64344.02
ETH 3142.36
USDT 1.00
SBD 4.01