CHIP Emulator(3)——OK!

在完成了CHIP8的核心实现后,剩下的事情就是完成画面和输入。为了逻辑区分不干扰,这一部分代码放在main.c函数中实现。其实这部分因为有关GLUT的应用,我也不是太了解,因为我的重点不是放在这上面,所以所做的就是把参考源码依瓢画葫芦,最终实现了CHIP8.

关于GLUT,首先你要进行安装,这里给出Linux下的安装方式GLUT安装

GLUT教程,网上找到了两个,一个是翻译了一部分的,一个原教程。看了以后,main.c中的代码就很容易理解了。对GLUT有兴趣的可以参考下面教程进行深入了解。

教程1:翻译教程
教程2:原教程(英文)

main.c代码:

#include <stdio.h>
#include <GL/glut.h>
#include "mychip8.h"

// Display size
#define SCREEN_WIDTH 64
#define SCREEN_HEIGHT 32

int modifier = 10;

// Window size
// int display_width = SCREEN_WIDTH * modifier;
// int display_height = SCREEN_HEIGHT * modifier;

 int display_width = 640;
 int display_height = 320;

void display();
void reshape_window(GLsizei w, GLsizei h);
void keyboardUp(unsigned char key, int x, int y);
void keyboardDown(unsigned char key, int x, int y);

// Use new drawing method
#define DRAWWITHTEXTURE
//typedef unsigned __int8 u8;

unsigned char screenData[SCREEN_HEIGHT][SCREEN_WIDTH][3]; 
void setupTexture();

int main(int argc, char **argv) 
{       
    if(argc < 2)
    {
        printf("Usage: myChip8.exe chip8application\n\n");
        return 1;
    }

    // Load game
    if(!LoadApp(argv[1]))       
        return 1;

    // Setup OpenGLabclixu123

    glutInit(&argc, argv);          
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);

    glutInitWindowSize(display_width, display_height);
    glutInitWindowPosition(320, 320);
    glutCreateWindow("myChip8 by Laurence Muller");

    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutReshapeFunc(reshape_window);        
    glutKeyboardFunc(keyboardDown);
    glutKeyboardUpFunc(keyboardUp); 

#ifdef DRAWWITHTEXTURE
    setupTexture();         
#endif  

    glutMainLoop(); 

    return 0;
}

// Setup Texture
void setupTexture()
{
    int x, y;
    // Clear screen
    for(y = 0; y < SCREEN_HEIGHT; ++y)      
        for(x = 0; x < SCREEN_WIDTH; ++x)
            screenData[y][x][0] = screenData[y][x][1] = screenData[y][x][2] = 0;

    // Create a texture 
    glTexImage2D(GL_TEXTURE_2D, 0, 3, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)screenData);

    // Set up the texture
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 

    // Enable textures
    glEnable(GL_TEXTURE_2D);
}

void updateTexture()
{   
    int x, y;
    // Update pixels
    for( y = 0; y < 32; ++y)        
        for( x = 0; x < 64; ++x)
            if(Gfx[(y * 64) + x] == 0)
                screenData[y][x][0] = screenData[y][x][1] = screenData[y][x][2] = 0;    // Disabled
            else 
                screenData[y][x][0] = screenData[y][x][1] = screenData[y][x][2] = 255;  // Enabled

    // Update Texture
    glTexSubImage2D(GL_TEXTURE_2D, 0 ,0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)screenData);

    glBegin( GL_QUADS );
        glTexCoord2d(0.0, 0.0);     glVertex2d(0.0,           0.0);
        glTexCoord2d(1.0, 0.0);     glVertex2d(display_width, 0.0);
        glTexCoord2d(1.0, 1.0);     glVertex2d(display_width, display_height);
        glTexCoord2d(0.0, 1.0);     glVertex2d(0.0,           display_height);
    glEnd();
}

// Old gfx code
void drawPixel(int x, int y)
{
    glBegin(GL_QUADS);
        glVertex3f((x * modifier) + 0.0f,     (y * modifier) + 0.0f,     0.0f);
        glVertex3f((x * modifier) + 0.0f,     (y * modifier) + modifier, 0.0f);
        glVertex3f((x * modifier) + modifier, (y * modifier) + modifier, 0.0f);
        glVertex3f((x * modifier) + modifier, (y * modifier) + 0.0f,     0.0f);
    glEnd();
}

void updateQuads()
{
    int x, y;
    // Draw
    for( y = 0; y < 32; ++y)        
        for( x = 0; x < 64; ++x)
        {
            if(Gfx[(y*64) + x] == 0) 
                glColor3f(0.0f,0.0f,0.0f);          
            else 
                glColor3f(1.0f,1.0f,1.0f);

            drawPixel(x, y);
        }
}

void display()
{
    HandleOpcode();

    if(DrawFlag)
    {
        // Clear framebuffer
        glClear(GL_COLOR_BUFFER_BIT);

#ifdef DRAWWITHTEXTURE
        updateTexture();
#else
        updateQuads();      
#endif          

        // Swap buffers!
        glutSwapBuffers();    

        // Processed frame
        DrawFlag = 0;
    }
}

void reshape_window(GLsizei w, GLsizei h)
{
    glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, w, h, 0);        
    glMatrixMode(GL_MODELVIEW);
    glViewport(0, 0, w, h);

    // Resize quad
    display_width = w;
    display_height = h;
}

void keyboardDown(unsigned char key, int x, int y)
{
    if(key == 27)    // esc
        ;//exit(0);

    if(key == '1')      Keyboard[0x1] = 1;
    else if(key == '2') Keyboard[0x2] = 1;
    else if(key == '3') Keyboard[0x3] = 1;
    else if(key == '4') Keyboard[0xC] = 1;

    else if(key == 'q') Keyboard[0x4] = 1;
    else if(key == 'w') Keyboard[0x5] = 1;
    else if(key == 'e') Keyboard[0x6] = 1;
    else if(key == 'r') Keyboard[0xD] = 1;

    else if(key == 'a') Keyboard[0x7] = 1;
    else if(key == 's') Keyboard[0x8] = 1;
    else if(key == 'd') Keyboard[0x9] = 1;
    else if(key == 'f') Keyboard[0xE] = 1;

    else if(key == 'z') Keyboard[0xA] = 1;
    else if(key == 'x') Keyboard[0x0] = 1;
    else if(key == 'c') Keyboard[0xB] = 1;
    else if(key == 'v') Keyboard[0xF] = 1;

    //printf("Press key %c\n", key);
}

void keyboardUp(unsigned char key, int x, int y)
{
    if(key == '1')      Keyboard[0x1] = 0;
    else if(key == '2') Keyboard[0x2] = 0;
    else if(key == '3') Keyboard[0x3] = 0;
    else if(key == '4') Keyboard[0xC] = 0;

    else if(key == 'q') Keyboard[0x4] = 0;
    else if(key == 'w') Keyboard[0x5] = 0;
    else if(key == 'e') Keyboard[0x6] = 0;
    else if(key == 'r') Keyboard[0xD] = 0;

    else if(key == 'a') Keyboard[0x7] = 0;
    else if(key == 's') Keyboard[0x8] = 0;
    else if(key == 'd') Keyboard[0x9] = 0;
    else if(key == 'f') Keyboard[0xE] = 0;

    else if(key == 'z') Keyboard[0xA] = 0;
    else if(key == 'x') Keyboard[0x0] = 0;
    else if(key == 'c') Keyboard[0xB] = 0;
    else if(key == 'v') Keyboard[0xF] = 0;
}

上述代码需要注意的是原作者给出了两种绘图方式。还有关于CHIP8的键盘,映射方式如下:

Keypad                   Keyboard
+-+-+-+-+                +-+-+-+-+
|1|2|3|C|                |1|2|3|4|
+-+-+-+-+                +-+-+-+-+
|4|5|6|D|                |Q|W|E|R|
+-+-+-+-+       =>       +-+-+-+-+
|7|8|9|E|                |A|S|D|F|
+-+-+-+-+                +-+-+-+-+
|A|0|B|F|                |Z|X|C|V|
+-+-+-+-+                +-+-+-+-+

最后编译生成可执行代码,然后运行游戏应用

./mychip8 pong2.c8

这是一个打乒乓的游戏,运行效果如下,如果没有接着球的话,命令终端就会打印出BEEP!
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值