如何在掩模图像上创建鼠标点击事件 [Pygame]
我刚开始学习编程,正在做一个类似于《Cookie Clicker》的游戏,不过有点不同,是关于挖矿的。这个游戏是用python和pygame做的。我有一张岩石的图片,每次点击它的时候,我想把一块石头加到我的游戏库存里。
之前有人帮我设置了一个叫point_collide的东西在我的类里。老实说,我不太明白它是怎么工作的,但它的作用是检测我的鼠标是否在岩石图片的非透明部分。
我希望游戏只有在你点击岩石图片的非透明部分时,才会给你一块石头。我把岩石图片放在屏幕中间。
简短的问题是:我该怎么设置游戏,让它只在我的遮罩图片上注册点击呢?
顺便说一下,我知道先学好编程基础会更好,但我通过直接投入项目学到了很多(这让我更有动力,也比看书有趣多了)。
代码链接:https://www.refheap.com/88634
代码:
import pygame, sys
from pygame.locals import *
from datetime import datetime
if (__name__ == "__main__"):
pygame.init()
pygame.font.init()
pygame.display.set_caption("Miner Click")
clock = pygame.time.Clock()
screen = pygame.display.set_mode((960,600))
width = 960
height = 600
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0,0,0)
WHITE = (255,255,255)
BROWN = (84,27,1)
GREY = (198,198,198)
greenbg = pygame.image.load("greenbg.jpg").convert()
rockbutton = pygame.image.load("rockbutton.png").convert_alpha()
woodbutton = pygame.image.load("woodbutton.png").convert_alpha()
pygame.mouse.set_visible(True)
pick = pygame.image.load("pick.png").convert_alpha()
axe = pygame.image.load("axesmall.png").convert_alpha()
rockwidth = 544
rockheight = 274
clicks = 0
wood = 0
stonefont = pygame.font.SysFont("verdana", 29, True)
woodfont = pygame.font.SysFont("verdana", 29, True)
clicktext = stonefont.render('Rock: ' +str(clicks), 2, (GREY))
woodtext = woodfont.render('Wood: ' +str(wood), 2, (BROWN))
boxsize = clicktext.get_rect()
RocksX = 125
WoodX = 113
class Rock(pygame.sprite.Sprite):
def __init__(self, color = BLUE, width = 544, height = 274):
super(Rock, self ).__init__()
self.image = pygame.Surface((width, height))
self.set_properties()
self.image.fill(color)
def set_properties(self):
self.rect = self.image.get_rect()
self.origin_x = self.rect.centerx
self.origin_y = self.rect.centery
def set_position(self, x, y):
self.rect.x = 250
self.rect.y = 230
def set_image(self, filename = None):
if (filename != None):
self.image = pygame.image.load(filename).convert_alpha()
def point_collide(self, point):
x, y = point
x -= self.rect.x
y -= self.rect.y
try:
return self.mask.get_at((x,y))
except IndexError:
return False
#below is my clueless attempt at getting it to work
def checkForCursorPressed(x,y):
if pygame.mouse.get_pressed() and pygame.mouse.get_pos() == (x,y):
clicks+=1
coordfont = pygame.font.SysFont("verdana", 12, True)
rock_group = pygame.sprite.Group()
rock = Rock()
rock.set_image("rock.png")
rock.set_position(width/2, height/2)
rock_group.add(rock)
while True:
clock.tick(60)
screen.fill((255,255,255))
screen.blit(greenbg, (0,0))
x,y = pygame.mouse.get_pos()
coords = x,y
now = datetime.now()
date = '%s/%s/%s' % (now.month, now.day, now.year)
label = coordfont.render("Coordinates: "+str(coords), 1, (GREY))
date = coordfont.render("Date: "+str(date), 1, (GREY))
screen.blit(date, (650,10))
screen.blit(label, (790, 10))
screen.blit(rockbutton, (25,25))
screen.blit(woodbutton, (25,100))
clicktext = stonefont.render(' ' +str(clicks), 2, (GREY))
woodtext = woodfont.render(' ' +str(wood), 2, (BROWN))
screen.blit(clicktext, [RocksX,38])
screen.blit(woodtext, [139,WoodX])
rock_group.draw(screen)
screen.blit(pick, (x-10,y-50))
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == KEYDOWN and event.key == K_ESCAPE:
sys.exit()
pygame.display.update()
#in case i need the below again
#if x>249 and x<(795) and y>210 and y<(484):
3 个回答
0
我也不太明白point_collide()是怎么工作的,而且我遇到了一个错误:'Rock'没有'mask'这个属性。为了检测点击图像中不透明的部分,我打算使用另一种方法,叫做colorkey。
colorkey是用来定义在绘制图像时哪个颜色是透明的。在我的例子中,透明色是白色:
def set_image(self, filename = None):
...
#sets colorkey to white, depends on the image
self.image.set_colorkey((255,255,255))
point_collide()的新版本:
def point_collide(self, point):
x, y = point
x -= self.rect.x
y -= self.rect.y
#detects if click hits the image
if 0 <= x < self.image.get_width():
if 0 <= y < self.image.get_height():
#detects if color at clicking position != colorkey-color(transparent)
if self.image.get_at((x,y))[0:3] != self.image.get_colorkey()[0:3]:
return True
return False
关于如何获取鼠标事件的问题已经有人回答过了。
0
好的,我搞定了 :)
如果其他人也在尝试做类似的事情,我在这里解释一下。
把下面的代码放到你的程序里(这解决了我遇到的“Rock没有属性mask”的错误)
self.mask = pygame.mask.from_surface(self.image)
这是我在代码中的位置(在我的set_image函数里)
def set_image(self, filename = None):
if (filename != None):
self.image = pygame.image.load(filename).convert_alpha()
self.mask = pygame.mask.from_surface(self.image)
现在把这段代码和Marius结合起来,就能完美运行了!
1
点击鼠标会产生一个叫做MOUSEBUTTONDOWN的事件,所以你可以在处理事件的循环中处理这些点击事件,比如:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == KEYDOWN and event.key == K_ESCAPE:
sys.exit()
elif event.type == MOUSEBUTTONDOWN:
click_position = event.pos
if rock.point_collide(click_position):
print('Clicked within the rock')
clicks += 1
# Any other events that have to happen
# when the rock is clicked