⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joy.c

📁 一个控制游戏控制杆的例子
💻 C
字号:
/*====================================================================*/
/*                                                                    */
/*  NOTE: Ensure this program is compiled for LARGE model.            */
/*        Non-ANSI stuff is pertinent to Microsoft QuickC v2.5.       */
/*        Porting to another compiler should not be too hard!         */
/*                                                                    */
/*====================================================================*/

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <memory.h>

#define FALSE         0
#define TRUE          1

#define FIRE_BUTTON1  0x01
#define FIRE_BUTTON2  0x02

#define BLACK         0         /*  Std colour for black in default palette  */
#define WHITE         15        /*  Std colour for white in default palette  */

typedef unsigned char BOOL;
typedef unsigned char BYTE;

/*  NB: Most of the functions below are to aid in the demonstration of the  */
/*  joystick routines. They are quick and simple - no effort has been made  */
/*  to make them efficient. Feel free to modify them as you require!        */

BYTE *pVideo=(BYTE *)0xA0000000L;       /*  Ptr to base of VGA video RAM  */

void SetVideoMode( int nMode )
{
    /*  Simple routine to set the video mode using the BIOS video interrupt  */

    _asm    mov ah, 00H
    _asm    mov al, byte ptr nMode
    _asm    int 10H
}

void SetPixel( int x, int y, int colour )
{
    /*  Very simple (inefficient) way of setting a pixel colour  */

    *(pVideo+(unsigned)y*320U+(unsigned)x) = (BYTE)colour;
}

void DrawCross( int cx, int cy, int colour )
{
    /*  Simple function to draw a 'cross-hair' cursor.  */

#define XWTH    4       /*  Aspect ration in 320x200 is approx 3/4  */
#define YHT     3

    int     x, y;

    if ( cx>=0 && cx<320 )
    {
        for ( y=cy-YHT; y<=cy+YHT; y++ )
        {
            if ( y>=0 && y<200 ) SetPixel( cx,y,colour );
        }
    }

    if ( cy>=0 && cy<200 )
    {
        for ( x=cx-XWTH; x<=cx+XWTH; x++ )
        {
            if ( x>=0 && x<320 ) SetPixel(x,cy,colour);
        }
    }
}

void SetCursorPos( int col, int row )
{
    /*  Even though we will be in graphics mode we can ask the video BIOS  */
    /*  to set our cursor position for displaying text...                  */

    _asm    mov ah, 02H
    _asm    mov bh, 00H
    _asm    mov dl, byte ptr col
    _asm    mov dh, byte ptr row
    _asm    int 10H
}

/*===========================================================================

    This text is taken from the RUTILS v2.0 manual:

         These two functions allow an application to interrogate the
         GAME port onto which up to two joysticks may be connected.
         These two joysticks are numbered 1 and 2 and are serviced by
         joystick_1() and joystick_2() respectively. Although these
         functions return x and y count positions of the joystick the
         values are NOT measured in screen or any other fixed units. In
         fact, they are PC dependant timing values which will differ
         from PC to PC. What this basically means is that an application
         will need to CALIBRATE the joystick functions before any of the
         results can be interpreted correctly. The calibration procedure
         involves the determination of the minimum and maximum x and y
         counts for joystick movement. This can really only be done by
         asking the user to move the joystick to the top left and bottom
         right respectively. In fact, some games ask the user to do this
         and press the fire button to confirm the action. Once these
         minimum and maximum values are known it is then a simple matter
         of scaling the range to fit the required screen (pixel)
         coordinates. The calibration procedure need only be performed
         for one joystick.

     Return Value:

         An integer representing a bit mask comprising of FIRE_BUTTON_1
         and/or FIRE_BUTTON_2. Each joystick has two fire buttons. If
         neither button is pressed 0 is returned.

     Example:

         The following shows how to calibrate a joystick:

         int  min_x,min_y,max_x,max_y;
         ...
         prints( "Move joystick to upper left & press FIRE\n\r",L_GREY,0 );
         while ( !joystick_1(&min_x,&min_y) );
         ...
         prints( "Move joystick to lower right & press FIRE\n\r",L_GREY,0 );
         while ( !joystick_1(&max_x,&max_y) );
         ...


         To scale a joystick "count" reading (j_x,j_y) to a pixel
         position on a graphics screen the following equations can be
         used:

         pixel_x = (j_x - min_x) * (VS.mx+1) / (max_x - min_x);
         pixel_y = (j_y - min_y) * (VS.my+1) / (max_y - min_y);

==============================================================================*/

int joystick_1( int *xc, int *yc )
{
    /*  Examine joystick 1  */

    unsigned int    i, count=0;
    unsigned char   state;

    *xc=*yc=0;

    _asm    mov dx, 0201H
    _asm    mov al, 0FFH
    _asm    out dx, al

    do
    {
        _asm    mov dx, 0201H
        _asm    in  al, dx
        _asm    mov state, al
        if ( state&0x01 ) *xc=count;
        if ( state&0x02 ) *yc=count;
        count++;
    }
    while ( state&0x03 && count<65535U );

    return( (int) ((state>>4)&0x03)^0x03 );
}

int joystick_2( int *xc, int *yc )
{
    /*  Examine joystick 2  */

    unsigned int    i, count=0;
    unsigned char   state;

    *xc=*yc=0;

    _asm    mov dx, 0201H
    _asm    mov al, 0FFH
    _asm    out dx, al

    do
    {
        _asm    mov dx, 0201H
        _asm    in  al, dx
        _asm    mov state, al
        if ( state&0x04 ) *xc=count;
        if ( state&0x08 ) *yc=count;
        count++;
    }
    while ( state&0x0c && count<65535U );

    return( (int) (state>>6)^0x03 );
}

/*========================= main program ====================================*/

void main( void )
{
    int     min_x, min_y, max_x, max_y, jx, jy, lastjx=-99, lastjy=-99;

    printf( "\n\nJoystick Demo\n=============\n\nPress ESCape at any time to abort\n\n" );

    /*  Calibrate the joystick by finding its lowest and highest values  */

    printf( "Calibrating:\n\nMove joystick to top left and press a fire button" );

    while ( !joystick_1(&min_x,&min_y) )
    {
        if ( kbhit() && getch()==27 ) exit( 1 );
    }

    /*  Ensure button released before we do next one. On a fast machine the  */
    /*  following loop will exit almost immediately 'cos the user hasn't     */
    /*  lifted his finger off the button yet...                              */

    while ( joystick_1(&jx,&jy) )
    {
        if ( kbhit() && getch()==27 ) exit( 1 );
    }

    printf( "\n\nMove joystick to bottom right and press a fire button" );

    while ( !joystick_1(&max_x,&max_y) )
    {
        if ( kbhit() && getch()==27 ) exit( 1 );
    }

    /*  Check for invalid range of values or idiot user(!)  */

    if ( min_x>=max_x || min_y>=max_y )
    {
        printf( "\n\nWooah! Wonky joystick dude!\n" );
        exit( 1 );
    }

    /*  Start the demo  */

    SetVideoMode( 0x13 );       /*  Set the magic 320x200x256 linear graphics mode  */

    while ( 1 )
    {
        int     buttons=joystick_1( &jx,&jy );

        /*  Check for exit  */

        if ( kbhit() && getch()==27 ) break;

        /*  Convert to pixel values  */

        if ( jx<min_x ) jx=min_x;       /*  Ensure within calibrated range  */
        if ( jx>max_x ) jx=max_x;
        if ( jy<min_y ) jy=min_y;
        if ( jy>max_y ) jy=max_y;

        jx = (int)((long)(jx-min_x)*320L / (long)(max_x-min_x));
        jy = (int)((long)(jy-min_y)*200L / (long)(max_y-min_y));

        /*  If changed from last position, update the cross hairs  */

        if ( lastjx!=jx || lastjy!=jy )
        {
            /*  Erase the original if required  */

            if ( lastjx!=-99 ) DrawCross(lastjx,lastjy,BLACK);

            /*  Now draw the new position and record it for later  */

            DrawCross( lastjx=jx,lastjy=jy,WHITE );
        }

        /*  Special POW! effect when a button pressed  */

        if ( buttons )
        {
            /* Convert pixel values to character positions. In 320x200, BIOS */
            /* font is 8x8 pixels in size...                                 */

            int     cx=jx/8-2, cy=jy/8, tx, ty;

            /*  Display POW!  */

            SetCursorPos( cx,cy );
            printf( "%s",(buttons&FIRE_BUTTON1?"Pow1":"Pow2") );

            /*  Wait for the button to be released  */

            while ( joystick_1(&tx,&ty) );

            /*  Remove POW! message and redraw cross hairs  */

            SetCursorPos( cx,cy );
            printf( "    " );
            DrawCross( lastjx,lastjy,WHITE );
        }
    }

    /*  Restore normal 80x25 text mode  */

    SetVideoMode( 0x03 );

    printf( "Joystick Demo Coded by CyberFrog 8:)\n\n" );
    printf( "Min Values: %u,%u\n",min_x,min_y );
    printf( "Max Values: %u,%u\n",max_x,max_y );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -