モノ創りで国造りを

ハード/ソフト問わず知見をまとめてます

子供が産まれました -1000人に一人の逸材-

はじめに

令和元年に子供が産まれました。元気な男の子です。
3人目の子供なので慣れたもんですが、久しぶりに見る新生児はちっこくてかわいい。
上の子がちょっと生意気になりつつある年齢なので、尚更かわいいです。

ちょっとした問題

しかし産まれてすぐに"先天性内反足"であることがわかりました。
足首から先が内側に曲がっているのです。
調べると1000人に一人の割合で存在し、原因は不明とのこと。
幸い治療方法はある程度確立しており、 矯正器具を付け時間をかけて足の曲がり具合を矯正する必要があるらしい。
患者数が少ないせいか近場の大学病院ですら対応できず、
車で1.5時間の病院に通うことになりました。
新生児には結構な苦痛だと思う。

f:id:yuji2yuji:20200115230440j:plain:w300
右足が内反足と思われる

この記事の趣旨

家族とはいえ自分以外のことをブログに書くのは気が引けますが、
自分の今の不安感を将来抱くかも知れない親御さんの励みになればと思い、
本記事を書き残すことにしました。

経過

通院1回目(出生後15日):

  • 症状確認のため触診してもらう
  • レントゲン撮影
  • 予想通り内反足との結果
  • 今後の説明を受ける
    • ギプスによる矯正で様子を見るが、場合によってはアキレス腱を切ったりもする
    • 毎週一回・合計10週、ギプスを巻くために通院する
  • ギプスを巻いてもらう
  • ギプスに関する注意事項を受講する
    • ギプスは通院前日の夜か当日の午前に家で取り外してから通院する
    • ギプスを巻いてから三日間はキッチンペーパーをギプスに巻き頻繁に取り換える(ギプスから水が滲み出るので)

診察だけのつもりだったのですが、まさか当日ギプスを巻いてもらうことになるとは驚きました。
7時に家を出て、家に着いたのが17時。新生児にはなかなかハードな一日だったと思います。
施術中は赤ん坊は違和感に耐えられず喚いてましたが、夜にはギプスを気にせず熟睡してました。ちょっと安心。
毎週平日の14時に通院する事になり、嫁一人に行ってもらうのも不安なので仕事をどうすべきか悩み中。

f:id:yuji2yuji:20200115225812j:plain:w300
ギプスを気にせず熟睡する赤ちゃん

通院2回目

続く

今更ですが、USB3.0を使いこなしたい

EZ-USB FX3の使い方

 

EZ-USB FX3とは:

 EZ-USB FX3とはUSB3.0を容易に使えるようにするためのIC。一般的なペリフェラル用IFに加えて柔軟に仕様を変更できる汎用のIFも備える。

f:id:yuji2yuji:20191205203216p:plain



IF:

・I2C:マスタとして動作、100kHz/200kHz/1MHz

・I2S:トランスミッタorレシーバとして動作、100kHz/400kHz/1MHz

・UART:フロー制御に対応、300bps ~ 4608Kbps

・SPI:トランザクションサイズは4bit~32bit、最大33MHz、4モードに対応

・GPIF Ⅱ:最大100MHz、8/16/32bit、プログラマブル、マスタorスレーブどちらも可能

 

 外部クロックは19.2MHz/26MHz/38.4MHz/52MHzに対応。内部で19.2MHzが生成される?

 電源は、各IF毎に異なる電圧を供給可能。

 

ブート方法:

 ブート方法はPMODEのピン設定で選択可能。通常は次のいずれかで行う。

 ・PMODE[2:0]  = F11:USBでファームウェアを読み込んで起動する

 ・PMODE[2:0]  = 0F1:SPI ROMで起動

EZ-USB FX3とFPGAとの接続:

 EZ-USB FX3はGPIF Ⅱを介してFPGAと接続可能。

f:id:yuji2yuji:20191205203247p:plain




FPGAコンフィギュレーションはEZ-USB FX3を介して行うことも可能。外部メモリを削減できる。

f:id:yuji2yuji:20191205203306p:plain


EZ-USB FX3とイメージセンサの接続:

 EZ-USB FX3はGPIF Ⅱを介してイメージセンサと接続できる。

f:id:yuji2yuji:20191205203327p:plain



外部デバイスとのデータ通信:

 EZ-USB EX3と外部デバイスはソケットを介して接続される。各ソケットはペリフェラル用IF毎に存在する。ただしGPIF はソケット4つあり?対応するソケットを介して接続される。スレッドとソケットは1:1対応。

f:id:yuji2yuji:20191205203352p:plain



自動DMAチャネル:

 GPIFソケットはDMAバッファが一杯になったことをUSBソケットに通知できる。

 USBソケットはDMAバッファが空になったことをGPIFソケットに通知できる。

 外部データを加工しない場合は上記の手法を用いる。

 

手動DMAチャネル:

 GPIFソケットはDMAバッファが一杯になったことをCPUに通知し、CPUはUSBソケットに伝達する。

 USBソケットはDMAバッファが空になったことをCPUに通知し、CPUはGPIFソケットに伝達する。

 外部データを加工する場合は上記の手法を用いる。

 

ソケットはデータ管理のため、DMAバッファアドレス、バッファサイズ、ディスクリプタチェーンを仕様する。つまり、アドレスとバッファサイズと次のアドレスのポインタを用いて順次データを転送する。

 

DMAディスクリプタの切り替えには数usの時間を要する。通常のデータ転送では非常に大きな時間である。DMAディスクリプタ変更の際に、アクティブなGPIFスレッド(ソケット)を切り替えることで待ち時間0で転送用DMAバッファを切り替えられる。

f:id:yuji2yuji:20191205203417p:plain



参考:

EZ-USB FX3 入門 https://www.cypress.com/file/140781/download

課題解決マトリクス(Yマトリクス)の考案

背景

前職のベンチャー企業に勤めているときに(現職もベンチャーだけど)、人手が足りず効率よく課題解決する必要性がありました。
課題の真因を把握するため「Whyを5回繰り返す」トヨタ方式にひと手間加える事で、
対策案も効率的に決められる手法を考案した(というほどでもないですが)周知・宣伝したいと思います。

*既にフレームワークとして世の中に知られている方法があるなら教えてください。悲しいですが車輪の再発明はしたくないので、今後はそれを参考にします。

Yマトリクス

Yの意味は、

  • Why(ワイ= Y )を5回繰り返す手法を元にしていることから
  • 複数の課題を一つの対策方法で対策するイメージ
  • 課題解決して問題を白紙(White)にしましょうという意味を込めて
  • 自分の名前の頭文字

手法

  1. 複数の課題を挙げる(縦軸に記載)
  2. 各課題についてWhyを繰り返す(縦軸に記載)
  3. 各Whyに対する解決法を考える(横軸に記載)
  4. 各々の解決方法が他のwhyを解決しうるか検討する(縦横の交叉)
  5. 実施する解決法を決める(横軸からピックアップ)

かなり私的な内容ですが、私個人の家庭事情を例にします。

家族構成:

  • 父親( 自分):サラリーマン
  • 母親(嫁):専業主婦、子供3人目を妊娠中
  • 子供1:4歳
  • 子供2:3歳

現場の状況と課題:

  • 住居は4LDK
  • 父親の職場が家から遠いため、平日は家事ができない
  • 母親が家事と子育てと妊娠で疲弊している
  • 子供がリビングでおもちゃを散らかす
  • 1部屋は洗濯物を部屋干ししている
  • 子供3人それぞれに部屋を提供できない

Yマトリクス

まだまだブラシュアップが必要だが、例としては以です。

f:id:yuji2yuji:20191023083323p:plain

繰り返しになりますが手順を再掲します。

  1. 複数の課題を挙げる(縦軸に記載)
  2. 各課題についてWhyを繰り返す(縦軸に記載)
  3. 各Whyに対する解決法を考える(横軸に記載)
  4. 各々の解決方法が他のwhyを解決しうるか検討する(縦横の交叉)
  5. 実施する解決法を決める(横軸からピックアップ)

加えて、全課題のWhyを眺めながら、複数の課題を網羅的に解決できる案を追加して、再検討すると良いです。
この作業に終わりはありません。納得するか時間の許す限り続けましょう。

宮本茂氏曰く「アイデアとは複数の課題をいっぺんに解決すること」。
解決策の捻出作業はクリエイティブであり、個性的を発揮できる場だと思っています。

今後の検討事項

上記の例では考慮していませんが、各課題は複数の真因のAND又はORで構成されていることがほとんどです。 また解決策によっては時間やお金がかかったり、リスクがあったり、何かを犠牲にしたりとデメリットは少なからずあります。
従って以下を考慮して解決策を検討する必要があります。

  • 課題の真因のAND/ORの考慮
  • 解決策のデメリット
  • 解決策間の関連性

MERNことはじめ

背景

MERN 開発の流れを知りたくてyotuube(https://www.youtube.com/watch?v=7CqJlxBYj-M)を見た。
動画は情報量が多くて捗るけど、その分繰り返し見るには時間がかかるので文字に起こした。

MongoDBの説明

  • Database
  • Collection
  • Document
  • Index
  • $lookup
  • Reference

Example

Mongo DBの例

{
    name:" ",
    title:" ",
    address:{
                address1:" ",
                city:" ",
                state: " ",
            },
    topics:[" ", " ", " ",],
    number:
}

MogoDB Atlasの紹介

512MBまで無料、Cluster使えるとか

作成するアプリの説明

Appは以下を含む

  • Exercises
  • Users

全てのエクササイズは一人のユーザーのみ持つ

ディレクトリの作成と環境の整備

特定のディレクトリで、

create-react-app mern-exercise-tracker

数分待って完了したらディレクトリ変更

cd mern-exercise-tracker

バックエンド用のディレクトリを作成し環境もろもろを整備する

mkdir backend
cd backend
npm install express cors mongoose dotenv
npm install -g nodemon

バックエンドとMongoDBの接続

backendディレクトリにserver.jsファイルを新規作成する。

const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');

require('dotenv').config();

const app = express();
const port = process.env.PORT || 5000;

app.use(cors());
app.use(express.json());

const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {userNewUrlParser: true, userCreateIndex: true });

const connection = mongoose.connection;
connection.once('open', () => {
    console.log("MongoDB database connection established successfully");
})

const exercisesRouter = require('./routes/exercises');
const usersRouter = require('./routes/users');

app.use('/exercises', exercisesRouter);
app.use('/users', usersRouter);


app.listen(port,() => {
    console.log(`Server is runnning on port: ${port}`);
});

backendディレクトリに.envファイルを新規作成する。
MongoDB Atlas clusterのconnection clusterのconnection String OnlyのCopyをクリック

.envに以下を記載。 ATLAS_URI=ペースト(先ほどコピーしたもの) passwordの箇所にパスワードを記載する。

backendディレクトリでnodemon server

以上でMongoDBにアクセスできるようになる。

modelの作成

backendにmodelsフォルダを作成。
modelsフォルダに

  • exercise.model.js
  • user.model.js

を新規作成する。
exercise.model.js

const mongoose = require('monngoose');

const Schema = mongoose.Schema;

const exerciseSchema = new Schema({
    username: { type: String, required: true},
    description: { type: String, required: true},
    duration: { type: Number, required: true},
    date: { type: Date, required: true},
}, {
    timestamps: true,
});

const Exercise = mongoose.model('Exercise', exerciseSchema);

module.exports = Exercise;

user.mode.js

const mongoose = require('monngoose');

const Schema = mongoose.Schema;

const userSchema = new Schema({
    username:{
        type: String,
        required: true,
        unique: true,
        trim: true,
        minlength: 3
    },
}, {
    timestamps: true,
});


const User = mongoose.model('User', userSchema);
module.exports = User;

Routeの作成

backendディレクトリ内にroutesディレクトリを作成する。
routesディレクトリ内に

  • exercises.js
  • users.js

を新規作成する。

exercises.js

const router = require('express').Router();
let Exercise = require('../models/exrecise.model');

router.route('/').get((req, res) => {
    Exercise.find()
        .then(exercises => res.json(exercises))
        .catch(err => res.status(400).json('Error: ' + err));
});

router.route('/add').post((req, res) => {
    const username = req.body.username;
    const description = req.body.description;
    const duration = Number(req.body.duration);
    const date = Date.parse(req.body.date);

    const newExercise = new Exercise({
        username,
        description,
        duration,
        date,
    });

    newExercise.save()
    .then(() => res.json('Exercise added!'))
    .catch(err => res.status(400).json('Error: ' + err));
});

module.exports = router;

user.js

const router = require('express').Router();
let User = require('../models/user.model');

router.route('/').get((req, res) => {
    User.find()
        .then(users => res.json(users))
        .catch(err => res.status(400).json('Error: ' + err));
});

router.route('/add').post((req, res) => {
    const username = req.body.username;
    const newUser = new User({username});

    newUser.save()
        .then(() => res.json('User added!'))
        .catch(err => res.status(400).json('Error: ' + err));
});

module.exports = router;

server.jsにルートを記載する(上述)。
---ここまで動画開始から30分---

データベースの確認

Insomniaでサーバーの動作を確認する。
exercises.jsにIDのルートの処理を追加する(上述)。
get,delete,postなど

---ここまで動画開始から43分。ここからReactの説明開始---

ReactでHello Worldの表示

publicのindex.htmlを確認する
index.jsを確認する
App.jsに移動。

exercise-trackerフォルダで

  • npm install bootstrap
  • npm install reat-router-dom

使用するコンポーネントをあらかじめimportする。
srcディレクトリ下にcomponentディレクトリを作成する。

その後

これ以降のReactの説明に関する情報は少し古い。
Hooksを使用するのが今後のトレンドになるはず。
従ってこれ以降は動画をまとめる必要はないような気がするので
代わりにReact Hooksについて読みかじったことを記載しておく。

参考文献

りあクト!
りあクト! TypeScriptで始めるつらくないReact開発 第2版 - くるみ割り書房 - BOOTH

react training公式ページ
React Training: React Router v5.1

Qiitaの記事

useStateの使い方

import React, {FC, useState } from 'react';
import { Button, Card, Statistic } from 'semantic-ui-react';

import './App.css';

const App:FC = () => {
    const [count, setCount] = usetState(0);
    const increment = () => {
        setCount(count + 1);
    };
    const decremet = () => {
        setCount(count -1);
    };

    return(
        <div className="container">
            <header>
                <h1>カウンター</h1>
            </header>
            <Card>
                <Statistic className="number-board">
                    <Statistic.Label>count</Statistic.Label>
                    <Statistic.value>{count}</Statistic.value>
                </Statistic>
                <Card.Content>
                    <div className="ui two buttons">
                        <Button color="red" onClick={decrement}>-1</Button>
                        <Button color="green" onClick={increment}>+1</Button>
                    </div>
                </Card.Content>
            </Card>
        </div>
    );
};

export default App;

useEffectの使い方

import React, {FC, useEffect, useState} from 'react';
import { Button, Card, Icon, Statistics } from 'semantic-ui-react';

import './App.css';

const LIMIT = 60;

const App:FC = () => {
    const [timeLeft, setTimeLeft] = useState(LIMIT);
    const reset = () => {
        setTimeLeft(LIMIT);
    };

    const tick = () => {
        setTimeLeft(prevTime => (prevTime === 0? LIMIT: prevTime -1));
    };

    useEffect(() => {
        const timerId = setInterval(tick, 1000);
        return () => clearInterval(timerId);
    },[]);

    return (
        <div className="container">
            <header>
                <h1>タイマー</h1>
            </header>
            <Card>
                <Statistic className="number-board">
                    <Statistics.Label>time</Statistics.Label>
                    <Statistics.value>{timeLeft}</Statistics.value>
                </Statistic>
                <Card.content>
                    <Button color="red" fluid on Click={reset}>
                        <Icon name="redo" />
                        Reset
                    </Button>
                </Card.content>
            </Card>
        </div>
    );
};

export default App;

Custom Hooksの例

import React, { FC, useEffect, useState } from 'react';
import AppComponent from ' ../components/App';

//Custom hook "useTimer"
const useTimer = (limitSec: number):[number, () => void] => {
    const [timeLeft, setTimeLeft] = useState(limitSec);

    const reset = () => {
        setTimeLeft(limitSec);
    };

    const tick = () => {
        setTimeLeft(prev => ( prevTime === 0? limitSec : prevTime -1));
    };

    useEffect(() => {
        const timerId = setInterval(tick, 1000);
        return () => clearInterval(timerId);
    },[]);

    return [timeLeft, reset];
}

const AppContainer: FC= () => {
    const LIMIT = 60;
    const [timeLeft, reset] = useTimer(LIMIT);

    return <AppComponent timeLeft={timeLeft} reset={reset} />;
};

export default AppContainer;

react-routerの例

import React from 'react';
import ReactDom from 'react-dom';
import {
    Browsewrrouter as router,
    Route,
    Switch,
    useParams,
    useHistory,
    useLocation,
} from 'react-router-dom';

function Hello(){
    const history = useHistory();
    return(
        <div>
            <h1>Hello</h1>
            <button onClick={() => history.push('/hello/react-router?message=hooks#test')}>Next</button>
        </div>
    );
}

function HelloSomeone(){
    const history = useHistory();
    const location = useLocation();
    const {name} = useParams();
    return(
        <div>
            <h1>Hello {name}</h1>
            <p>pathname: {location.pathname}</p>
            <p>search: {location.search} </p>
            <p>hash: {location.hash}</p>
            <button onClick={() => history.goBack()}>Go Back</button>
        </div>
    );
}

function App(){
    return (
        <Router>
            <Switch>
                <Route path="/" exact>
                    <Hello />
                </Route>
                <Route path="/hello/:name" exact>
                    <HelloSomeone/>
                </Route>
            </Switch>
        </Router>
    );
}

react-reduxの例

Yocto Projectの勉強まとめ(途中)

背景

SoC FPGAを搭載したオリジナル基板を開発できるようになりたい。
Linux使えれば色々便利。
基板毎に最適化された組込みLinux OSを作成できるYocto Projectなるものを知ったので勉強したい。

参考文献

https://www.miraclelinux.com/product-service/total-embedded/emb-mtrls/materials/yocto-project-introduction

Linuxディストリビューション

Linuxカーネル + 各種ライブラリ = Linux OS
各種ライブラリにはOSSプロジェクトも含まれる。

頒布方法

一連の流れ:
ソースコード => ダウンロード => コンパイル => バイナリ => インストール

バイナリーベース:
ディストリビューターコンパイル済のソフトウェアをパッケージとして頒布。
パッケージにはバイナリとインストール方法をまとめられている。
ユーザーはそのパッケージをインストールする。

ソースベース:
ディストリビューターコンパイル方法を頒布する。
ユーザーがコンパイルしインストールする。

Yocto Projectとは

Yocto Projectは組み込み向けOS開発を構築する仕組みを提供するプロジェクト。
ソースコードベース。

プロジェクト体制:

Poky

Pokyとは

レシピとは

設定ファイルとは

  • 拡張子は.conf
  • CPUアーキテクチャなどのターゲットマシン毎の定義
  • ビルド環境などの独自設定

bitbakeとは

  • Pythonで書かれたビルドツール
  • レシピを解析し、定義された動作を実行する

bitbakeの動作

  1. レシピを解析
  2. ソースコードのダウンロード
    • どこからダウンロードするか
    • do_fetch
  3. ソースコードの展開
    • どのように展開するか
    • do_unpack
  4. パッチの適用
    • どのようなパッチを適用するか
    • do_patch
  5. ソフトウェアのコンパイル
    • コンパイル方法の指定
    • 依存関係の記述
    • do_configure
    • do_compile
  6. 生成物をパッケージ化
    • インストール先
    • どのファイルを含むか
    • パッケージング方式の指定
    • do_install
    • do_package

レイヤー機能

まだ。

MAX10で画像処理

背景

FPGAで画像処理をしたい。
SoC FPGAでやろうと思ったけど、学習コストが高く、途中で挫折してしまった。
一旦、FPGAマイコンをハード的に分けることで何かしらの進捗を出し、モチベーションを高める。

やりたいこと

  1. カメラモジュールをマイコン(Arduino)のI2Cで制御。
  2. カメラモジュールの画像データをFPGAに出力。
  3. 画像データをFPGA内部で処理。
  4. FPGAからVGA信号をディスプレイに出力。

各モジュールの簡単な説明

マイコン

言わずと知れたArduino Uno。
f:id:yuji2yuji:20190926065121p:plain

カメラモジュール

OV7675のモジュール品を使用する。
秋月で購入。550円。安い。
OV7675使用30万画素カメラ B0070: カメラ 秋月電子通商-電子部品・ネット通販

供給電源は3.3V、出力形式は選択可能。
画像データはパラレル8出力。
f:id:yuji2yuji:20190926064847p:plain

1~4ピン(電源、GND、I2C)をArduinoに接続する。

MAX10 EVAL Kit

Intelから販売されているMAX10の安価な評価ボード。
FPGAへのデータ書き込みには専用のツールが必要。
https://www.intel.co.jp/content/www/jp/ja/programmable/products/boards_and_kits/dev-kits/altera/kit-max-10-evaluation.html

f:id:yuji2yuji:20190926065603p:plain

f:id:yuji2yuji:20190926065648p:plain

カメラモジュールをマイコンのI2Cで制御

OV7675カメラモジュールのデータは以下。
細かい点は色々あるが、まずはデータを出力できればよい。
真っ黒だとデータが出力されているかどうかが不明なのでつらい。

http://akizukidenshi.com/download/ds/omnivision/ov7675.pdf

データシートから、何かしらの画像データを出力するために以下の設定が必要とわかる。

ENとPWDNは以下の設定が必要。

Pin Level
PWDN L
PEN H

初期化時に各アドレスへ送信するデータは以下。

address data description
0xB8 4'h1 1.8V requirement
0xB8 4'h2 1.8V requirement
0x71 0x01 Test pattern Enable
0x17 Horizontal start
0x18 Horizontal stop
0x32 Horizontal start[2:0] and stop[5:3]
0x19 Vertical start
0x1A Vertical stop
0x03 Vertical start[2:0] and stop[5:3]

スレーブアドレスは、Write0x42、Read0x43。
Write/Readで末尾に1/0を付加されている。
一般的にI2Cで使用される7bitのアドレスは0x21。

Direction b6 b5 b4 b3 b2 b1 b0 W/R
Write 0 1 0 0 0 0 1 1
Read 0 1 0 0 0 0 1 0

OV7675カメラモジュールとArduinoを接続する。

SCCB(I2C)でデータの送受信を行う。
ArduinoはI2Cのポートを有するが、Digital IOポートを使ってSCCBの制御を行っているコードをgithubで見つけた。ただしOV7670。
https://gist.github.com/muhammadyaseen/75490348a4644dcbc70f
これを修正すればよさそう。
Arduino一つで複数カメラの制御もできそうなので、
今後の拡張性を考慮してありがたく拝借して使用する。

OV7675の画素はベイヤパターン。
f:id:yuji2yuji:20190926073254p:plain

しかしレジスタの設定を変えることで、出力Formatは変更可能。
今回はRGB565でやってみる。
RGB565は、R:5bit、G:6bit、B:5bitの合計16bitを1画素のデータとするFormat。

OV7675は画像データの表示領域を選択できる。
0x17~0x1A、0x03、0x32で設定する。
f:id:yuji2yuji:20190926073344p:plain

VGAのデータ出威力ダイアグラムは以下。 f:id:yuji2yuji:20190927073822p:plain
データをディスプレイ上に表示するためには、VGAを使ったアナログ信号だとDAコンバータが必要。
今回はDAコンバーターがないので、デジタルデータを閾値で0/1切り替えて表示する。

とりあえず画像だし

FPGAにデータを書き込み、OV7675を初期化すると画像が出るようになった。
ただし、FPGAによるVGA出力とOV7675のデータ入力は同期をとっていないので、
表示される画像はひどい有様だった。

そこで、OV7675から入力されるPCLK信号(画素データのクロック)を使ってFPGAからVGAデータを出力したところ、
画像が表示されなかった(入力データがない状態)。
波形を観測すると、PCLKは鈍っており十分な信号レベルが出力されていないことがわかった。
コンパレーターかアンプが必要とわかったが、そこまで改修するのも手間なので、今回はここまでとする。

pyxelで遊ぶ

背景

Pythonで簡単にドット絵ゲームが作成できるpyxelなるものを知ったので、
Pythonの復習がてら使ってみる。

pyxle

日本人が開発したPythonによるレトロゲームエンジン。

https://github.com/kitao/pyxel/blob/master/README.ja.md

関数を削減して、覚えるよりも作ることに注力できる。学習コストが極めて低い。

ドット絵やサウンドエフェクトの開発ツールも同梱されている。

なんか作ってみる

とりあえずカラフルなエフェクトを作ってみた。
f:id:yuji2yuji:20190904135838g:plain

from pyxel import init, run, circ, cls 
from math import  sin, cos

class App:
    def __init__(self):
        init(160,120)
        self.i = 0
        run(self.update, self.draw)

    def update(self):
        self.i += 1
        self.i %= 1000
    def draw(self):
        cls(1)
        for j in range(1500):
            circ(80+j/(50.1-2*self.i/4)*sin(j/2),60+j/(50.1-2*self.i/4)*cos(j/2),1,(j+self.i)%15)

App()

何でもない画像だけど、これだけでも楽しい。ドット絵だからなのか。
これがドット絵の魔力・・・

ゲームでも作ってみる

せっかくなのでゲームでも作ってみる。

企画

ざっくりとした仕様

  • 横スクロールアクション
  • 自キャラのアクション
    • 左右への移動
    • ジャンプ
    • 攻撃
  • 敵キャラのアクション
    • 左右への移動

絶賛作成中!!

途中経過

左右に移動+ジャンプ+攻撃(火の玉を出す)

f:id:yuji2yuji:20190905180044g:plain

移動時に画像を変えたいけど、画像を作るのがつらい・・・
昔からゲーム作成の肝は画像作成だと思っています。