使用godot制作超级马里奥1-1之主角制作

对于马里奥这个主角的制作相对会比较麻烦,因为马里奥多种形态,变大和变小,还有变成无敌那种状态,使用godot本身的动画效果比较不好处理,所以当时我就想了一些方法来处理。以下是马里奥的几种状态.

动画.gif

动画1.gif

动画10.gif

动画104.gif
大致是这些变化,当然还有其它拉旗,进入到水管和变小之类的就不一一展示,大致的动画的制作基本一致。那么简单说下这些动画是怎么制作的,首先的话需要对马里奥的动画进行一个分类,应该每个动画会有不同的颜色和大小,当时基本是同一类型的。

图片11211.png

图片111.png
然后就把每种的状态的动画分类,这样的话可以选择任何一种动画进行播放。马里奥的每种状态的切换都是用了状态模式来进行,就是走路的状态和站立的状态,每个状态单独处理逻辑。每个状态之间根据情况进行切换,这样简化了逻辑的处理。

func _update(delta):
	if status==constants.stand:
		stand(delta)
	elif status==constants.walk:
		walk(delta)
	elif status==constants.fall:
		fall(delta)
	elif status==constants.jump:
		jump(delta)	
	elif status==constants.small2big:
		pass
	elif status==constants.big2fire:
		fireState(delta)
	elif status==constants.big2small:
		pass
	elif status==constants.crouch:
		crouch(delta)
	elif status==constants.deadJump:
		deathJump(delta)	
	elif status==constants.poleSliding:
		poleSliding(delta)
	elif status==constants.walkingToCastle:
		walkingToCastle(delta)
	elif status==constants.sitBottomOfPole:
		sitBottomOfPole(delta)
	elif status==constants.stop:
		pass	
	elif status==constants.pipeIn:
		pipeIn(delta)
		pass	
	elif status==constants.walkInPipe:
		walkIntoPipe(delta)
		pass
	elif status==constants.pipeOut:
		pipeOut(delta)	
	if status!=constants.big2small&&status!=constants.big2fire&&\
		status!=constants.small2big:	
		specialState(delta)
	if debug:	
		update()	
	pass
复制代码

就拿马里奥走路来说,走路的速度越快,动画变化的越快,这个可以根据移动速度修改动画的播放速度就可以做到,其它的话就是根据按键修改速度。对于转向的可以修改动画的flip_h的值。

func walk(delta):
	if xVel>0 || xVel<0:
		ani.speed_scale=1+abs(xVel)/constants.marioAniSpeed
	
	if Input.is_action_pressed("ui_action"):
		acceleration=constants.runAcceleration
		maxXVel=constants.marioRunMaxSpeed
		if fire&&allowShoot:
			shootFireball(false)
			allowShoot=false
	else:
		acceleration=constants.acceleration
		maxXVel=constants.marioWalkMaxSpeed	
		allowShoot=true
		
	#跳跃
	if Input.is_action_pressed("ui_jump"):
		yVel=-constants.marioJumpSpeed
		gravity=constants.marioJumpGravity
		status=constants.jump
		playJumpSound()
#		print('walk jump')
		return
	
	if Input.is_action_pressed("ui_down") &&big:
		startCrouch()
		return
	elif isCrouch and big:
		rect=Rect2(Vector2(-11,-30),Vector2(22,60))	
		position.y-=14
		ani.position.y=0
		isCrouch=false
	
	if Input.is_action_pressed("ui_left"):
		if xVel>0: #反方向
			animation("slide")
			acceleration=constants.slideFriction
		else:
			acceleration=constants.acceleration
			dir=constants.left
			animation('walk')
			
		if 	xVel>-maxXVel:
			xVel-=acceleration*delta
		else:
			xVel=-maxXVel
			
	elif Input.is_action_pressed("ui_right"):
		if xVel<0:
			animation("slide")
			acceleration=constants.slideFriction
		else:
			dir=constants.right
			acceleration=constants.acceleration
			animation('walk')
			
		if 	xVel<maxXVel:
			xVel+=acceleration*delta
		else:
			xVel=maxXVel
	else:
		if dir==constants.right:
			if	xVel>0:
				xVel-=acceleration*delta
				animation("walk")
			else:
				ani.speed_scale=1
				status=constants.stand	
		else:
			if xVel<0:
				xVel+=acceleration*delta
				animation("walk")
			else:
				ani.speed_scale=1
				status=constants.stand	
		
	position.x+=xVel*delta
	if !isOnFloor:
		ani.stop()
		status=constants.fall
	pass
复制代码

马里奥变大或者变小需要对每帧播放时修改动画的位置,这个是因为动画图片大小不一,但是动画的显示是剧中显示的问题。

图片781.png

func _on_ani_frame_changed():
	if status==constants.small2big:
#		print(ani.frame)
		if ani.frame in [0,2,4]:
			ani.position.y= 0
		else:
			ani.position.y=-18
	elif ani.animation in throw_animation:
		throwAniFinish=true
	elif status	==constants.big2small:
		if ani.frame in [0]:
			ani.position.y= 0
		elif ani.frame in [2,4,6,8]:
			ani.position.y=20	
		else:
			 ani.position.y= 0
		pass
	if invincible:
		shadow.frame=ani.frame
	pass # Replace with function body.


func _on_ani_animation_finished():
	if status==constants.small2big:
		big=true
		ani.position.y=0
		status=preStatus
		rect=Rect2(Vector2(-11,-30),Vector2(22,60))	
		Game.emit_signal('stateFinish')
	elif status==constants.big2small:
		hurtInvincible=true
		status=preStatus
		big=false
		fire=false
		position.y+=15
		aniIndex=0
		rect=Rect2(Vector2(-10,-16),Vector2(20,32))	
		Game.emit_signal('stateFinish')
	
	pass # Replace with function body.

复制代码

在马里奥吃到星星的时候,会不停的变色,这个的话用godot的动画是没办法实现出来,所以我想到了用两个动画的方式,第二个动画不播放,然后根据第一个动画播放啥第二个动画也跟着播放啥,然后不停的更改自身的动画颜色实现不停的变色,前面把同一个类型放在一个数组里,所以只要改变数组下标就可以了。

图片44441.png

发射火球的动画需要控制等火球那一帧动画结束后在播放其它动画。其它的内容暂时没想到,想到在补充。

参考资料:
github.com/absolve/god… (项目文件夹mario1)
godotengine.org/

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享