ZX81の回想禄

PR

×

プロフィール

ZX81

ZX81

カレンダー

コメント新着

コメントに書き込みはありません。

キーワードサーチ

▼キーワード検索

2026.06.18
XML

時間がかかりましたが、
ここまで検討した結果をソースに反映させます。

ーーーーーobjects.h
/*
 *      ZX81 Objects Handling Module header
 */
#ifndef _ZX81_OBJECTS_H
#define _ZX81_OBJECTS_H
// objects functions
void objects_init(void);
void objects_move(int dy);
void objects_update(int render_pos);
void objects_render();
#endif  // _ZX81_OBJECTS_H
ーーーーーobjects.cpp
/*
 *      ZX81 Objects Handling Module program
 */
#include <stdio.h>
#include <string.h>
#include "map.h"
#include "objects.h"
typedef enum {
    OBJ_NONE,
    OBJ_WHIRL,
    OBJ_ENEMY,
    OBJ_CROC,
    OBJ_BARREL,
    OBJ_RAFT,
    OBJ_DRIFTER,
    OBJ_MAX
} ObjectType;
#define WHIRL_CW    5
#define WHIRL_CH    5
unsigned char whirl_chr[2][WHIRL_CW*WHIRL_CH] = {
 {0x87,0x03,0x01,0x87,0x00, 0x05,0x00,0x03,0x04,0x04, 0x05,0x05,0x00,0x01,0x05, 0x87,0x02,0x01,0x87,0x01, 0x00,0x00,0x03,0x01,0x00},
 {0x00,0x00,0x83,0x04,0x00, 0x02,0x87,0x04,0x02,0x04, 0x04,0x05,0x00,0x04,0x05, 0x05,0x00,0x83,0x01,0x00, 0x02,0x83,0x00,0x02,0x00}
};
#define ENEMY_CW    3
#define ENEMY_CH    5
unsigned char enemy_chr[4][ENEMY_CW*ENEMY_CH] = {
 {0x80,0x81,0x05, 0x05,0x00,0x05, 0x80,0x84,0x05, 0x02,0x07,0x00, 0x00,0x00,0x00},
 {0x85,0x82,0x80, 0x85,0x00,0x85, 0x85,0x07,0x80, 0x00,0x84,0x01, 0x00,0x00,0x00},
 {0x83,0x87,0x04, 0x07,0x03,0x05, 0x82,0x83,0x05, 0x84,0x81,0x01, 0x00,0x01,0x00},
 {0x87,0x04,0x83, 0x85,0x03,0x84, 0x85,0x83,0x81, 0x02,0x82,0x07, 0x00,0x02,0x00}
};
#define CROC_CW     3
#define CROC_CH     5
unsigned char croc_chr[4][CROC_CW*CROC_CH] = {
 {0x84,0x04,0x00, 0x84,0x80,0x04, 0x81,0x80,0x00, 0x85,0x07,0x01, 0x00,0x01,0x00},
 {0x02,0x82,0x00, 0x02,0x80,0x82, 0x87,0x80,0x05, 0x00,0x80,0x03, 0x00,0x02,0x00},
 {0x00,0x87,0x04, 0x87,0x80,0x04, 0x84,0x80,0x00, 0x81,0x80,0x01, 0x00,0x07,0x00},
 {0x00,0x00,0x83, 0x00,0x81,0x82, 0x02,0x80,0x05, 0x87,0x80,0x07, 0x00,0x85,0x01}
};
#define BARREL_CW   3
#define BARREL_CH   4
unsigned char barrel_chr[4][BARREL_CW*BARREL_CH] = {
 {0x07,0x84,0x00, 0x07,0x84,0x00, 0x07,0x84,0x00, 0x03,0x03,0x00},
 {0x85,0x03,0x05, 0x85,0x03,0x05, 0x85,0x03,0x05, 0x02,0x03,0x01},
 {0x83,0x83,0x00, 0x82,0x81,0x00, 0x82,0x81,0x00, 0x82,0x81,0x00},
 {0x87,0x83,0x04, 0x85,0x83,0x05, 0x85,0x83,0x05, 0x85,0x83,0x05}
};
#define RAFT_CW     3
#define RAFT_CH     4
unsigned char raft_chr[4][RAFT_CW*RAFT_CH] = {
{0x06,0x86,0x00, 0x05,0x85,0x00, 0x07,0x84,0x00, 0x02,0x01,0x00},
{0x87,0x03,0x04, 0x85,0x00,0x05, 0x85,0x03,0x05, 0x00,0x03,0x00},
{0x87,0x04,0x00, 0x05,0x85,0x00, 0x82,0x81,0x00, 0x86,0x06,0x00},
{0x00,0x83,0x00, 0x85,0x00,0x05, 0x85,0x83,0x05, 0x02,0x83,0x01},
};
#define DRIFTER_CW  3
#define DRIFTER_CH  3
unsigned char drifter_chr[5][DRIFTER_CW*DRIFTER_CH] = {
 {0x04,0x04,0x04, 0x84,0x80,0x01, 0x00,0x00,0x00},
 {0x87,0x87,0x87, 0x02,0x80,0x07, 0x00,0x00,0x00},
 {0x04,0x00,0x04, 0x86,0x82,0x01, 0x02,0x03,0x00},
 {0x87,0x00,0x87, 0x02,0x81,0x06, 0x00,0x03,0x01},
 {0x06,0x07,0x04, 0x84,0x84,0x01, 0x00,0x00,0x00}
};
// object table
#define OBJECTS_MAX   9
struct {
    int y;
    int x;
    ObjectType type;
} objects_tbl[OBJECTS_MAX]  =
{
 {230,10, OBJ_ENEMY},
 {210,13, OBJ_CROC},
 {190,8,  OBJ_BARREL},
 {170,13, OBJ_RAFT},
 {150,8,  OBJ_DRIFTER},
 { 50,11, OBJ_WHIRL},
 { 74,4,  OBJ_WHIRL},
 {125,6,  OBJ_WHIRL},
 {200,13, OBJ_WHIRL}
};
// active table
#define ACTIVE_MAX   5
struct {
    int y;                  // 画面上のY座標
    int x;                  // 画面上のX座標
    int h;                  // 描画文字の高さ
    int w;                  // 描画文字の幅
    int area;               // w * h のキャッシュ
    unsigned char *p;       // 描画文字のポインタ
    ObjectType type;        // オブジェクト種別
    int speed_y;  // Y移動速度(0=移動しない、1=毎回, 2=2回に1回)
    int speed_cnt;// カウンタ(speed_y で初期化)
} active_tbl[ACTIVE_MAX];
// render size
#define RENDER_DX22
#define RENDER_DY24
// objects出現位置
static unsigned int  objects_y;
// ----------------------------------------------------------
// 初期化
// ----------------------------------------------------------
void objects_init(void)
{
    int  i;
    for (i = 0; i < ACTIVE_MAX; i++)
    {
        active_tbl[i].type = OBJ_NONE;
    }
    objects_y = 0xffff;
}
// ----------------------------------------------------------
// 出現
// ----------------------------------------------------------
static void objects_active(int obj_no)
{
    int  i;
    unsigned char *chrp;
    int chrw, chrh;
    int speed_y;
    for (i = 0; i < ACTIVE_MAX; i++)
    {
        if (active_tbl[i].type == OBJ_NONE)
        {
            break;
        }
    }
    if (i == ACTIVE_MAX)
    {
        return;
    }
    speed_y = 4;
    switch (objects_tbl[obj_no].type)
    {
        case OBJ_WHIRL:
            chrp = &whirl_chr[0][0];
            chrw = WHIRL_CW;
            chrh = WHIRL_CH;
            speed_y = 0;
            break;
        case OBJ_ENEMY:
            chrp = &enemy_chr[0][0];
            chrw = ENEMY_CW;
            chrh = ENEMY_CH;
            break;
        case OBJ_CROC:
            chrp = &croc_chr[0][0];
            chrw = CROC_CW;
            chrh = CROC_CH;
            speed_y = 2;
            break;
        case OBJ_BARREL:
            chrp = &barrel_chr[0][0];
            chrw = BARREL_CW;
            chrh = BARREL_CH;
            break;
        case OBJ_RAFT:
            chrp = &raft_chr[0][0];
            chrw = RAFT_CW;
            chrh = RAFT_CH;
            break;
        case OBJ_DRIFTER:
            chrp = &drifter_chr[0][0];
            chrw = DRIFTER_CW;
            chrh = DRIFTER_CH;
            break;
        default:
            return;
    }
    active_tbl[i].y = 1;
    active_tbl[i].x = objects_tbl[obj_no].x;
    active_tbl[i].w = chrw;
    active_tbl[i].h = chrh;
    active_tbl[i].area = chrw*chrh;
    active_tbl[i].p = chrp;
    active_tbl[i].type = objects_tbl[obj_no].type;
    active_tbl[i].speed_y = speed_y;
    active_tbl[i].speed_cnt = speed_y;
}
// ----------------------------------------------------------
// 更新
// ----------------------------------------------------------
void objects_update(int render_pos)
{
    int obj_no;
    int obj_y;
    // 出現位置の更新チェック
    obj_y = (render_pos + 1) / 4;
    if (objects_y <= obj_y)
    {
        return;
    }
    objects_y = obj_y;
    // 出現位置の更新によるオブジェクト出現処理
    for (obj_no = 0; obj_no < OBJECTS_MAX; obj_no++)
    {
        if (objects_tbl[obj_no].y == obj_y)
        {
            break;
        }
    }
    if (obj_no == OBJECTS_MAX)
    {
        return;
    }
    objects_active(obj_no);
}
// ----------------------------------------------------------
// 移動
// ----------------------------------------------------------
void objects_move(int dy)
{
    int act_no, obj_y;
    for (act_no = 0; act_no < ACTIVE_MAX; act_no++)
    {
        switch (active_tbl[act_no].type)
        {
            case OBJ_WHIRL:
            case OBJ_ENEMY:
            case OBJ_CROC:
            case OBJ_BARREL:
            case OBJ_RAFT:
            case OBJ_DRIFTER:
                break;
            default:
                continue;
        }
        if (active_tbl[act_no].speed_y != 0)
        {
            active_tbl[act_no].speed_cnt--;
            if (active_tbl[act_no].speed_cnt == 0)
            {
                active_tbl[act_no].y++;
                active_tbl[act_no].speed_cnt = active_tbl[act_no].speed_y;
            }
        }
        active_tbl[act_no].y -= dy;
        // 画面外は消去
        obj_y = active_tbl[act_no].y / 2;
        if ((obj_y < 0) ||
            (obj_y > 23 + active_tbl[act_no].h))
        {
            active_tbl[act_no].type = OBJ_NONE;
        }
    }
}
// ----------------------------------------------------------
// 描画
// ----------------------------------------------------------
void objects_render()
{
    int act_no, obj_y, y;
    unsigned char *chrp;
    unsigned char *pos;
    int chrw, chrh, dy;
    for (act_no = 0; act_no < ACTIVE_MAX; act_no++)
    {
        if (active_tbl[act_no].type == OBJ_NONE)
        {
            continue;
        }
        chrp = active_tbl[act_no].p;
        if (active_tbl[act_no].type == OBJ_WHIRL)
        {
            if (active_tbl[act_no].y & 0x01)
            {
                chrp += active_tbl[act_no].area;
            }
        }
        else
        {
            if (active_tbl[act_no].x & 0x01)
            {
                chrp += active_tbl[act_no].area;
            }
            if (active_tbl[act_no].y & 0x01)
            {
                chrp += active_tbl[act_no].area * 2;
            }
        }
        obj_y = (active_tbl[act_no].y / 2) - active_tbl[act_no].h;
        if (obj_y < 0)
        {
            pos = getrenderaddr(0, active_tbl[act_no].x);
        }
        else
        {
            pos = getrenderaddr(obj_y, active_tbl[act_no].x);
        }
        chrw = active_tbl[act_no].w;
        chrh = active_tbl[act_no].h;
        dy = obj_y;
        for (y = 0; y < chrh; y++)
        {
            if ((dy <= 23) && (dy >= 0))
            {
                memcpy(pos, chrp, chrw);
            }
            if (dy >= 0)
            {
                pos += RENDER_DX;
            }
            chrp += chrw;
            dy++;
        }
    }
}

渦はobjectsの中に含めたので、whirl.hとwhirl.cは削除しました。

川の位置がobject_tblの位置に到達したら
対象のObjectTypeをavtive_tblにて最高5つまで管理し
画面からoutするまで動きと描画を行います。

それぞれにY座標の移動速度を設定できるため
より完成に近づいてきました。



ただし、衝突判定と横移動は未実装ですので
順次検討していきます。







お気に入りの記事を「いいね!」で応援しよう

最終更新日  2026.06.18 20:30:55コメント(0) | コメントを書く
[ZX81C言語でのプログラム開発] カテゴリの最新記事


【毎日開催】
15記事にいいね!で1ポイント
10秒滞在
いいね! -- / --
おめでとうございます!
ミッションを達成しました。
※「ポイントを獲得する」ボタンを押すと広告が表示されます。
x
X

© Rakuten Group, Inc.
X
Design a Mobile Website
スマートフォン版を閲覧 | PC版を閲覧
Share by: