zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
    【POJ 2152】 Fire (树形DP)
    【POJ 1741】 Tree (树的点分治)
    【POJ 2486】 Apple Tree (树形DP)
    【HDU 3810】 Magina (01背包,优先队列优化,并查集)
    【SGU 390】Tickets (数位DP)
    【SPOJ 2319】 BIGSEQ
    【SPOJ 1182】 SORTBIT
    【HDU 5456】 Matches Puzzle Game (数位DP)
    【HDU 3652】 B-number (数位DP)
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/3334104.html
Copyright © 2011-2022 走看看