• Programming 2D Games 读书笔记(第五章)


     

    http://www.programming2dgames.com/chapter5.htm

    示例一:Planet

    真正示例的开始,首先是载入2张图片

    1.Graphics添加了2个方法

    loadTexture和drawSprite

    loadTexture方法得到一个IRECT3DTEXTURE9接口

    //=============================================================================
    // Load the texture into default D3D memory (normal texture use)
    // For internal engine use only. Use the TextureManager class to load game textures.
    // Pre: filename is name of texture file.
    //      transcolor is transparent color
    // Post: width and height = size of texture
    //       texture points to texture
    // Returns HRESULT
    //=============================================================================
    HRESULT Graphics::loadTexture(const char *filename, COLOR_ARGB transcolor,
                                    UINT &width, UINT &height, LP_TEXTURE &texture)
    {
        // The struct for reading file info
        D3DXIMAGE_INFO info;
        result = E_FAIL;
    
        try{
            if(filename == NULL)
            {
                texture = NULL;
                return D3DERR_INVALIDCALL;
            }
        
            // Get width and height from file
            result = D3DXGetImageInfoFromFile(filename, &info);
            if (result != D3D_OK)
                return result;
            width = info.Width;
            height = info.Height;
        
            // Create the new texture by loading from file
            result = D3DXCreateTextureFromFileEx( 
                device3d,           //3D device
                filename,           //image filename
                info.Width,         //texture width
                info.Height,        //texture height
                1,                  //mip-map levels (1 for no chain)
                0,                  //usage
                D3DFMT_UNKNOWN,     //surface format (default)
                D3DPOOL_DEFAULT,    //memory class for the texture
                D3DX_DEFAULT,       //image filter
                D3DX_DEFAULT,       //mip filter
                transcolor,         //color key for transparency
                &info,              //bitmap file info (from loaded file)
                NULL,               //color palette
                &texture );         //destination texture
    
        } catch(...)
        {
            throw(GameError(gameErrorNS::FATAL_ERROR, "Error in Graphics::loadTexture"));
        }
        return result;
    }

    drawSprite方法则是画精灵元素

    //=============================================================================
    // Draw the sprite described in SpriteData structure
    // Color is optional, it is applied like a filter, WHITE is default (no change)
    // Pre : sprite->Begin() is called
    // Post: sprite->End() is called
    // spriteData.rect defines the portion of spriteData.texture to draw
    //   spriteData.rect.right must be right edge + 1
    //   spriteData.rect.bottom must be bottom edge + 1
    //=============================================================================
    void Graphics::drawSprite(const SpriteData &spriteData, COLOR_ARGB color)
    {
        if(spriteData.texture == NULL)      // if no texture
            return;
    
        // Find center of sprite
        D3DXVECTOR2 spriteCenter=D3DXVECTOR2((float)(spriteData.width/2*spriteData.scale),
                                            (float)(spriteData.height/2*spriteData.scale));
        // Screen position of the sprite
        D3DXVECTOR2 translate=D3DXVECTOR2((float)spriteData.x,(float)spriteData.y);
        // Scaling X,Y
        D3DXVECTOR2 scaling(spriteData.scale,spriteData.scale);
        if (spriteData.flipHorizontal)  // if flip horizontal
        {
            scaling.x *= -1;            // negative X scale to flip
            // Get center of flipped image.
            spriteCenter.x -= (float)(spriteData.width*spriteData.scale);
            // Flip occurs around left edge, translate right to put
            // Flipped image in same location as original.
            translate.x += (float)(spriteData.width*spriteData.scale);
        }
        if (spriteData.flipVertical)    // if flip vertical
        {
            scaling.y *= -1;            // negative Y scale to flip
            // Get center of flipped image
            spriteCenter.y -= (float)(spriteData.height*spriteData.scale);
            // Flip occurs around top edge, translate down to put
            // Flipped image in same location as original.
            translate.y += (float)(spriteData.height*spriteData.scale);
        }
        // Create a matrix to rotate, scale and position our sprite
        D3DXMATRIX matrix;
        D3DXMatrixTransformation2D(
            &matrix,                // the matrix
            NULL,                   // keep origin at top left when scaling
            0.0f,                   // no scaling rotation
            &scaling,               // scale amount
            &spriteCenter,          // rotation center
            (float)(spriteData.angle),  // rotation angle
            &translate);            // X,Y location
    
        // Tell the sprite about the matrix "Hello Neo"
        sprite->SetTransform(&matrix);
    
        // Draw the sprite
        sprite->Draw(spriteData.texture,&spriteData.rect,NULL,NULL,color);
    }

    2.Texture的2个包装类

    TextureManager(依赖loadTexture)用于载入一个IRECT3DTEXTURE9对象,Image类(依赖drawSprite)用于获取TextureManager的IRECT3DTEXTURE9对象并进行绘制

    image

    TextureManager

    //=============================================================================
    // Loads the texture file from disk.
    // Post: returns true if successful, false if failed
    //=============================================================================
    bool TextureManager::initialize(Graphics *g, const char *f)
    {
        try{
            graphics = g;                       // the graphics object
            file = f;                           // the texture file
    
            hr = graphics->loadTexture(file, TRANSCOLOR, width, height, texture);
            if (FAILED(hr))
            {
                SAFE_RELEASE(texture);
                return false;
            }
        }
        catch(...) {return false;}
        initialized = true;                    // set true when successfully initialized
        return true;
    }

    Image

    //=============================================================================
    // Draw this image using the specified SpriteData.
    //   The current SpriteData.rect is used to select the texture.
    // Pre : spriteBegin() is called
    // Post: spriteEnd() is called
    //=============================================================================
    void Image::draw(SpriteData sd, COLOR_ARGB color)
    {
        if (!visible || graphics == NULL)
            return;
        sd.rect = spriteData.rect;                  // use this Images rect to select texture
        sd.texture = textureManager->getTexture();  // get fresh texture incase onReset() was called
    
        if(color == graphicsNS::FILTER)             // if draw with filter
            graphics->drawSprite(sd, colorFilter);  // use colorFilter
        else
            graphics->drawSprite(sd, color);        // use color as filter
    }

    Spacewar载入图片

    1.initialize

    //=============================================================================
    // Initializes the game
    // Throws GameError on error
    //=============================================================================
    void Spacewar::initialize(HWND hwnd)
    {
        Game::initialize(hwnd); // throws GameError
    
        // nebula texture
        if (!nebulaTexture.initialize(graphics,NEBULA_IMAGE))
            throw(GameError(gameErrorNS::FATAL_ERROR, "Error initializing nebula texture"));
    
        // planet texture
        if (!planetTexture.initialize(graphics,PLANET_IMAGE))
            throw(GameError(gameErrorNS::FATAL_ERROR, "Error initializing planet texture"));
    
        // nebula
        if (!nebula.initialize(graphics,0,0,0,&nebulaTexture))
            throw(GameError(gameErrorNS::FATAL_ERROR, "Error initializing nebula"));
    
        // planet
        if (!planet.initialize(graphics,0,0,0,&planetTexture))
            throw(GameError(gameErrorNS::FATAL_ERROR, "Error initializing planet"));
        // place planet in center of screen
        planet.setX(GAME_WIDTH*0.5f  - planet.getWidth()*0.5f);
        planet.setY(GAME_HEIGHT*0.5f - planet.getHeight()*0.5f);
    
        return;
    }

    2.render

    //=============================================================================
    // Render game items
    //=============================================================================
    void Spacewar::render()
    {
        graphics->spriteBegin();                // begin drawing sprites
    
        nebula.draw();                          // add the orion nebula to the scene
        planet.draw();                          // add the planet to the scene
    
        graphics->spriteEnd();                  // end drawing sprites
    }

    呈现了2个图片

    image

    示例二:Spaceship

    动画

    image

    重复更新1张图的4个位置

    //=============================================================================
    // update
    // typically called once per frame
    // frameTime is used to regulate the speed of movement and animation
    //=============================================================================
    void Image::update(float frameTime)
    {
        if (endFrame - startFrame > 0)          // if animated sprite
        {
            animTimer += frameTime;             // total elapsed time
            if (animTimer > frameDelay)
            {
                animTimer -= frameDelay;
                currentFrame++;
                if (currentFrame < startFrame || currentFrame > endFrame)
                {
                    if(loop == true)            // if looping animation
                        currentFrame = startFrame;
                    else                        // not looping animation
                    {
                        currentFrame = endFrame;
                        animComplete = true;    // animation complete
                    }
                }
                setRect();                      // set spriteData.rect
            }
        }
    }
    
    //=============================================================================
    //  Set spriteData.rect to draw currentFrame
    //=============================================================================
    inline void Image::setRect() 
    {
        // configure spriteData.rect to draw currentFrame
        spriteData.rect.left = (currentFrame % cols) * spriteData.width;
        // right edge + 1
        spriteData.rect.right = spriteData.rect.left + spriteData.width;
        spriteData.rect.top = (currentFrame / cols) * spriteData.height;
        // bottom edge + 1
        spriteData.rect.bottom = spriteData.rect.top + spriteData.height;       
    }
    

    示例三:Spaceship Movement

    各种效果叠加组成的动画效果(图片更换,角度,大小,位置)来模拟

    //=============================================================================
    // Update all game items
    //=============================================================================
    void Spacewar::update()
    {
        ship.update(frameTime);
        ship.setDegrees(ship.getDegrees() + frameTime * ROTATION_RATE); // rotate ship
        ship.setScale(ship.getScale() - frameTime * SCALE_RATE);    // make ship smaller
        ship.setX(ship.getX() + frameTime * SHIP_SPEED);    // move ship right
        if (ship.getX() > GAME_WIDTH)                       // if off screen right
        {
            ship.setX((float)-ship.getWidth());             // position off screen left
            ship.setScale(SHIP_SCALE);                      // set to starting size
        }
    }
    

    示例四:Spaceship Control

    根据键盘来移动元素

    //=============================================================================
    // Update all game items
    //=============================================================================
    void Spacewar::update()
    {
        if(input->isKeyDown(SHIP_RIGHT_KEY))            // if move right
        {
            ship.setX(ship.getX() + frameTime * SHIP_SPEED);
            if (ship.getX() > GAME_WIDTH)               // if off screen right
                ship.setX((float)-ship.getWidth());     // position off screen left
        }
        if(input->isKeyDown(SHIP_LEFT_KEY))             // if move left
        {
            ship.setX(ship.getX() - frameTime * SHIP_SPEED);
            if (ship.getX() < -ship.getWidth())         // if off screen left
                ship.setX((float)GAME_WIDTH);           // position off screen right
        }
        if(input->isKeyDown(SHIP_UP_KEY))               // if move up
        {
            ship.setY(ship.getY() - frameTime * SHIP_SPEED);
            if (ship.getY() < -ship.getHeight())        // if off screen top
                ship.setY((float)GAME_HEIGHT);          // position off screen bottom
        }
        if(input->isKeyDown(SHIP_DOWN_KEY))             // if move down
        {
            ship.setY(ship.getY() + frameTime * SHIP_SPEED);
            if (ship.getY() > GAME_HEIGHT)              // if off screen bottom
                ship.setY((float)-ship.getHeight());    // position off screen top
        }
    
        ship.update(frameTime);
    }
    
  • 相关阅读:
    微信坚硬的后脚跟
    [项目整理]Win32,MFC的可执行文件只能运行一次
    美司法部索要维基解密志愿者谷歌账户内容
    QML性能
    OSGi 的核心配置、动态化及问题
    OSGi 的由来和本质特性
    机器视觉与计算机视觉
    人工智能与深度学习
    活着就能改变世界
    选择与执行
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/3334104.html
Copyright © 2020-2023  润新知