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

📄 tutorial.txt

📁 乒乓球游戏程序
💻 TXT
字号:
A better input system
*********************

The old input system was really just a quick hack.  It wasn't
very versatile, and the global variables were messy.  In this
chapter we'll implement a better input module, which will be
more versatile.  This will, in particular, allow us to treat
any of several devices in the same way within the game; the
effect of this is that our game code will not need to know
exactly what type of input device it is using.

Setting up the new input module
===============================

The new input module will of course have an initialisation
function and a shutdown function.  It will also have a set of
functions with which the game code can choose input devices,
with names such as `input_create_keyboard'.  There will be an
update function whose job it is to gather all the input.  Other
modules will be able to read this input through pointers
returned by the `input_create_*' functions.  These pointers
will point at structs like this:

     struct input_t {
         int x, y, fire1, fire2;
     };

`x' and `y' are the X and Y states of the input device; -1
means left or up, 0 means centre, and 1 means right or down.
The `fire1' and `fire2' fields show the states of two fire
buttons; 1 is pressed, 0 is not pressed.

How the module works internally
===============================

Internally the module must store a list of registered devices.
For each device it must have a `struct input_t', as above, which
will be updated by `input_update', and the address of which will
be returned to the game code from `input_create_*'.  Each device
also needs some setup information -- for the keyboard this
contains the scancodes for the keys that are bound to each
function, for the joystick it is the number of the stick (1 or
2), and for the mouse it is the sensitivity.  We also need to
know what type each device is, of course.

All of this information is stored in the struct
`input_internal_t'.

     struct input_internal_t {
         struct input_t input;     /* the struct we'll show to the other modules */
         int type;                 /* e.g. keyboard, joystick, mouse */
         union {
             struct input_kbd_t kbd;     /* keyboard data (keys to use) */
             struct input_mse_t mse;     /* mouse data (sensitivity) */
             struct input_joy_t joy;     /* joystick data (none) */
         } data;
         struct input_internal_t *next;  /* this is a linked list */
     };

The `input_kbd_t', `input_mse_t' and `input_joy_t' structs are
also declared in `input.c'.  All of these are local to the
input module, as is the linked list of `input_internal_t'
structs.

When a new device is created, a new node is added to the list,
and its fields are set up for the new device.  The pointer
returned to the game code is the address of the `input' field
of the above struct.

When `input_update' is called it walks the linked list, updating
all of the `input' fields, using the other information in the
above struct to do so.  Then the other modules can read
directly from the `input' fields, by dereferencing their
pointers.  See `bat.c' for an example.

Changes to other modules
========================

As noted above, the bat module has had to change to be able to
read from the new input information.  The `bat_t' struct now
contains a field for the pointer to the `input_t' struct, and
the initialisation function accepts the value for this pointer
as a parameter.

The objects module has also changed, so that it passes this
parameter to the bat module.  It creates an input device in its
init routine.  It doesn't destroy the device itself, but that
doesn't matter because the input module destroys all devices on
shutdown.

You can change which device is created by modifying the code in
the `objects_init' routine, in `objects.c'.  Obviously this is
not ideal; it would be better to be able to choose a device and
configure it at run-time, but that will have to wait until we've
written a better front end.

Note on the system being used
=============================

The system implemented here is a digital system; joysticks are
treated digitally, the keyboard is (necessarily) digital, and
the mouse is rather awkwardly treated as a digital device too.
The `x' and `y' fields of `input_t' structs are always 0, -1 or
1.

This is fine for the keyboard and not too bad for the joystick,
but for the mouse it's a bit of a pain.  Moving the mouse
quickly doesn't help at all; the maximum speed of the bat is
very slow.  There are a number of possible changes that would
alter this behaviour.

Firstly, and most obviously, we can make the whole system
analogue.  This would be great for mice and analogue joysticks;
for digital joysticks and the keyboard we'd need to scale the
values to get reasonable speeds, or make them behave in a more
sophisticated way (as damped acceleration devices).  This
generally works quite well, but it always means that digital
devices are more limited than analogue devices.  Well, that goes
without saying.

The alternative is to continue to treat devices as digital, but
alter the mouse device slightly so that your mouse movement is
cumulative.  This would be like having an invisible mouse
pointer in the arena and making the bat always move towards the
pointer.  This can work well, but it can feel awkward too if
the user doesn't know what to expect.

Which system you should use depends, of course, on what sort of
system works best with your game.  In Pong I don't think it
matters too much which of the latter two is chosen; perhaps the
first option is best.  The currently implemented system is
rather awkward to use with the mouse, but we won't change it
yet.

⌨️ 快捷键说明

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