前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Gameboy游戏开发-精灵高阶

Gameboy游戏开发-精灵高阶

作者头像
海哥@开发
发布2022-04-06 14:58:41
3520
发布2022-04-06 14:58:41
举报
文章被收录于专栏:海哥聊技术

上节课聊到了精灵的反向问题,GB因为卡带容量的限制不可能每个方向都单独制作,一般ACT类游戏只需要一个侧面,另一个方向是通过瓦块的镜像的来实现的。我们使用的gbdk类库提供了一个`set_sprite_prop`方法,看文档该方法会接收一个8位的值,其中第5位为1时对应的精灵会做水平翻转。我们来看一下例子。

精灵的水平翻转

我们还是用上节课的例子来继续修改,我们的精灵当时做的是向右侧的。现在我们来修改一下当摇杆操作向左的时候进行镜像操作。

代码语言:javascript
复制
else if(joypad()==J_LEFT)
{
    set_sprite_tile(0, (run_index+4)*2);
    set_sprite_tile(1, (run_index+4)*2+2);

    //向左走时,水平镜像精灵。因为我们的角色是两个精灵拼合出来的,所以需要分别进行镜像。
    set_sprite_prop(0, S_FLIPX);
    set_sprite_prop(1, S_FLIPX);

    scroll_sprite(0, -2, 0);
    scroll_sprite(1, -2, 0);

    if(run_index==4)
    {
        run_index = 0;
    }
    else
    {
        run_index+=2;
    }
}

运行看看效果,人物被镜像了。但.....恩对我们是原地镜像的。所以左右侧两个精灵没有调整位置。接下来我们来解决这个问题

GB游戏角色类

我们尝试封装一个游戏精灵类,默认是按16x16来支持,也就是同时支持两个瓦块。

首先我们新建一个 game_role.h 的头文件

代码语言:javascript
复制
#include <gb/gb.h>
#include <stdio.h>
/**
 * 游戏内角色的结构体,因为GB的机能限制,最大只支持8x16像素的sprit,
 * 因为我们每个角色使用32x32才能表示,所以一个数组来存储精灵的索引
 */
struct GameRole
{
    //精灵两个下标的存放数组
    UBYTE spritids[2];
    //精灵运动起来时的动画针索引
    UINT8 spritrun[3];
    //精灵的运动状态
    UINT8 spite_run_status;
    //精灵的x坐标
    UINT8 x;
    //精灵的y坐标
  UINT8 y;
    //精灵的面部朝向
    //1上,2右,3下,4左。我们这次只用左右方向即可
    UINT8 direction;
};

//单个精灵瓦块的宽度
UINT8 sprite_size = 8;

/**
 * 移动精灵方法,我们要在.c文件中实现的
 */
void movegamecharacter(struct GameRole* character, UINT8 x, UINT8 y);

我们再新建一个类文件 game_role.c

代码语言:javascript
复制
#include "game_role.h"
/**
 * 移动精灵方法的实现
 */
void movegamecharacter(struct GameRole* character, UINT8 x, UINT8 y)
{
    //随着精灵的运动修改精灵的下标
    if(character->spite_run_status==2)
    {
        character->spite_run_status = 0;
    }
    else
    {
        character->spite_run_status++;
    }
    //运动状态时循环显示几个针的动画
    set_sprite_tile(character->spritids[0], character->spritrun[character->spite_run_status]);
    set_sprite_tile(character->spritids[1], character->spritrun[character->spite_run_status]+2);

    if(x<character->x && character->direction==2) {
        //向左移动
        set_sprite_prop(character->spritids[0],S_FLIPX);
        set_sprite_prop(character->spritids[1],S_FLIPX);
        character->direction = 4;
    }

    if(x>character->x && character->direction == 4) {
        //向右移动
        set_sprite_prop(character->spritids[0],!(S_FLIPX));
        set_sprite_prop(character->spritids[1],!(S_FLIPX));
        character->direction = 2;
    }
    //根据移动方向,移动精灵位置
    if(character->x!=x || character->y!=y) {
        if(character->direction ==2){
            move_sprite(character->spritids[0], x-4, y);
            move_sprite(character->spritids[1], x + sprite_size-4, y);
        }
        else if (character->direction == 4)
        {
            move_sprite(character->spritids[0], x, y);
            move_sprite(character->spritids[1], x - sprite_size, y);
        }
    }
}

接下来我们在主文件中引入此文件并重构下主文件,删除掉向左右移动时的代码。

代码语言:javascript
复制
#include <gb/gb.h>
#include <stdio.h>
#include "game_role.h"
#include "mario.c"

//定义角色
struct GameRole role;

/**
 * 新增加的方法,初始化角色
 */
void initRole(UINT8 x, UINT8 y) 
{
    role.x = 0;
    role.y = 0;
    role.spritrun[0] = 8;
    role.spritrun[1] = 12;
    role.spritrun[2] = 16;
    role.spite_run_status = 0;
    set_sprite_tile(0, role.spritrun[role.spite_run_status]);
    role.spritids[0] = 0;
    set_sprite_tile(1, role.spritrun[role.spite_run_status]+2);
    role.spritids[1] = 1;
    role.direction = 2;
    movegamecharacter(&role,x,y);
    role.x = x;
    role.y = y;
}

/**
 * 新的mian方法
 */
void main()
{
    SPRITES_8x16;
    set_sprite_data(0, 20, mario);
    initRole(28,112);
    SHOW_SPRITES;
    while (1)
    {
        if(joypad()==J_RIGHT)
        {
            movegamecharacter(&role,role.x+2,role.y);
            role.x +=2;
            
        }
        else if(joypad()==J_LEFT)
        {
            movegamecharacter(&role,role.x-2,role.y);
            role.x -= 2 ;
        }
        else 
        {
            set_sprite_tile(0, 0);
            set_sprite_tile(1, 2);
        }
        delay(80);
    }
    
}

这会儿咱们的main方法重构完更简洁了。因为我们增加了一个类文件进来,在make前,我们还要修改下Makefile文件。

代码语言:javascript
复制
CC = /opt/gbdk/bin/lcc -Wa-l -Wl-m -Wl-j
BINS = main.gb

all:  $(BINS)

%.o:  %.c
  $(CC) -c -o $@ $<

%.gb:  main.o game_role.o
  $(CC) -o $@ $^

clean:
  rm -f *.o *.lst *.map *.gb *~ *.rel *.cdb *.ihx *.lnk *.sym *.asm

`make` 运行。

原计划本课还会讲到调色板,但因为咱们重构了一下角色类。内容有点多,怕知识点吸收不好,调色板的内容我向后放了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 海哥聊技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档