2020年07月31日

GearHead SDL 版を Linux Mint 18.3 32bit でコンパイルしました

5 年ぶり二度目. あのとき, 手順をメモしておかなかったおかげで, 5 年後の自分が苦労している. もう苦労したくないので, 今度は書いておきます.

参考ページ http://www.fenix.ne.jp/~G-HAL/scribble/gearhead/gearhead1.scribble#build

1. libiconv をインストール
https://www.kkaneko.jp/tools/ubuntu/gcc10.html の "libiconv のインストール" に書いてある通りにします.
以下はコピー.
$ cd /tmp
$ wget https://ftp.gnu.org/gnu/libiconv/libiconv-1.16.tar.gz
$ rm -rf libiconv-1.16
$ tar -xvzof libiconv-1.16.tar.gz
$ cd libiconv-1.16
$ mkdir build
$ cd build
$ ../configure --with-mpfr --with-gmp --prefix=/usr/local --enable-static --enable-shared
$ make -j2
$ sudo make install

2. /usr/local/lib/ 以下のライブラリが使えるようにする
http://weble.org/2011/12/20/ubuntu-ld-so-conf
を参考に作業します. 以下はほぼコピー.
私は vim を使いましたが, 他のエディタでも構いません.
$ sudo vim /etc/ld.so.conf
次の一行を追加.
include /usr/local/lib
設定を反映させる.
$ sudo ldconfig

3. SDL-ttf をインストール
$ sudo apt install libsdl-ttf2.0-dev

4. smpeg をインストール
$ sudo apt install libsmpeg-dev
他にもインストールする必要があるライブラリがあるはずですが,
私の環境ではすでにインストールされていたようです.

5. Free Pascal をインストール.
$ sudo apt install fpc-3.0.0

6. コンパイル
$ cd ~
$ wget https://sourceforge.net/projects/gearhead/files/gearhead/1.100/gh-1100-src.zip/download -O gh-1100-src.zip
$ wget http://www.fenix.ne.jp/~G-HAL/scribble/gearhead/GearHead1-I18N.data.jp.zip
$ wget http://www.fenix.ne.jp/~G-HAL/scribble/gearhead/GearHead1-I18N.image.zip
$ wget http://www.fenix.ne.jp/~G-HAL/scribble/gearhead/GearHead1-I18N.sound.zip
$ wget http://www.fenix.ne.jp/~G-HAL/scribble/gearhead/GearHead1-I18N.src.zip
$ unzip gh-1100-src.zip
$ mv GearHead GH1
$ unzip -d GH1 GearHead1-I18N.src.zip
$ unzip -o GearHead1-I18N.image.zip
$ unzip -o GearHead1-I18N.sound.zip
$ unzip -o GearHead1-I18N.data.jp.zip
$ cd GH1/build/xterm-boxdrawing
$ mv * ../../xterm-boxdrawing
$ cd ..
$ rm -r xterm-boxdrawing
$ mv * ../
$ rm -r build
$ /bin/sh ./build.sh sdl clean build nolibiconv_plug nolibc_iconv
$ mv build.sdl.Linux_athlon/gharena gharena
$ rm -r build.sdl.Linux_athlon

7. 環境変数を設定する
$HOME/.profile に環境変数 GEARHEAD_LANG を追加します.
下の一行は vim を使う場合.
$ vim ~/.profile
以下三行を追加します.

if [ -d "$HOME/GH1" ] ; then
    export GEARHEAD_LANG=ja_JP.UTF-8
fi

GEARHEAD_LANG の値については,
環境によって適切なものを選ぶ必要があるはずです.
以下のコマンドで設定を反映.
$ source ~/.profile

8. gharena.cfg
$ ./gharena
起動すると, ほとんどの文字が四角になっています.
一番下の項目で Enter を押して終了します.
起動したことで $HOME/.config/gharena/ に
gharena.cfg が作製されます.
GH1/gharena.cfg.jp_debianlinux を参考にフォントを変更します.
もう一度
$ ./gharena
と入力し起動すると, 文字化けは解消しているはずです.
linuxgh1title.png

これで完成です.

9. 次回以降の起動方法

$ cd ~
$ cd GH1
$ ./gharena
で起動できます.

posted by Takenoko at 20:59| Comment(0) | game | このブログの読者になる | 更新情報をチェックする

2020年07月26日

Python 3 で, Ogg Vorbis と Wave を再生する Player を書きました 続き

pysoundsample.png

前回 の続きです. 上の画像は, sample の gui です.

Ogg Vorbis ファイルと, Wave ファイルを複数同時に再生できるプレイヤーです. MIT License です. 使用方法は, zip 内の readme.txt と, sample.py に書いてあります. 下にあるコードも, zip 内に全て入っています.

マルチスレッドによるエラーを対策したり, wave の再生終了まで待機できるようにしたりしました. 他の変更点はコード冒頭 update.txt に書いてあります.


'''
thread2.py  v1.1

参考ページ: Python スレッドの停止と再開の簡易サンプル
https://qiita.com/BlueSilverCat/items/44a0a2a3c45fc3e88b19
'''

from threading import Thread, Event

class Thread2(Thread):

    def __init__(self, daemon = True, callback = 0):
        super().__init__(daemon = daemon)
        self.started = Event()
        self.alive = 1
        self.active = 1
        self.callback = callback
        self.start()

    def __del__(self):
        self.kill()

    def begin(self):
        self.started.set()
        self.active = 1

    def end(self):
        self.active = 0
        self.started.clear()
        if callable(self.callback):
            self.callback()

    def kill(self):
        self.started.set()
        self.active = 0
        self.alive = 0
        self.join()




'''
soundthread.py  v1.2
'''

from threading import Lock

from pyaudio import PyAudio

from .thread2 import Thread2

class SoundThread(Thread2):

    __lock = Lock()

    def __init__(self, callback):
        super().__init__(callback = callback)

    def close(self):
        self.stream.stop_stream()
        self.stream.close()
        self.p.terminate()

    def kill(self):
        self.close()
        self.end()
        super().kill()

    def open(self, format, channels, rate):
        SoundThread.__lock.acquire()
        self.p = PyAudio()  # 使い回すとエラーが出ることがある
        self.stream = self.p.open(format = format,
                                  channels = channels,
                                  rate = rate,
                                  output = True)
        SoundThread.__lock.release()

    def run(self):
        while self.active:
            self.play()  # Sub Class で実装すること
            self.started.wait()




'''
player.py  v1.0
'''

class Player:

    def __init__(self, enabled):
        self.__enabled = enabled  # False で関数呼び出しを無視する

    def is_enabled(self):
        return self.__enabled

    def on(self):
        if self.__enabled:
            return
        self.__enabled = 1

    def off(self):
        if not self.__enabled:
            return
        self.__enabled = 0




'''
vorbisplayer.py  v1.3

Copyright (c) 2020 Takenoko (http://nekokiss.seesaa.net/)
Released under the MIT license.
see https://opensource.org/licenses/MIT

PyAudio, PyOgg, audio-metadata が install されている必要があります.
'''

import time
from threading import Event

import pyogg as po
import pyaudio as pa

from .soundthread import SoundThread
from .player import Player

class Vorbis:

    def __init__(self, ogg, chunk, loop, tagloop):
        self.ogg = ogg
        self.loop = loop
        self.file = po.VorbisFile(ogg)
        '''
        bit rate size
        1, 3, 4 等の場合もあるかもしれないが,
        取得方法がわからないので 2 で固定
        '''
        self.sampwidth = 2
        # block size
        self.block = (self.sampwidth
                      * self.file.channels)
        self.format = pa.get_format_from_width(self.sampwidth)
        self.cache = {}
        '''
        Loop Tag
        '''
        self.loopstart = 0
        self.loopend = (self.file.buffer_length
                        * self.block)
        if loop and tagloop:
            import audio_metadata as am
            md = am.load(ogg)
            if 'tags' in md and 'loopstart' in md.tags:
                self.loopstart = int(md.tags.loopstart[0]) * self.block
                if 'looplength' in md.tags:
                    self.loopend = (int(md.tags.looplength[0])
                                    * self.block + self.loopstart)
        self.chunk = chunk
        if self.loopend - self.loopstart < self.chunk:
            self.chunk = self.loopend - self.loopstart

    def getdata(self, start):
        if start not in self.cache:
            end = start + self.chunk
            if end > self.loopend:
                data = self.file.buffer[start:self.loopend]
                if self.loop:
                    end = self.loopstart + end - self.loopend
                    data += self.file.buffer[self.loopstart:end]
                else:
                    end = -1
                self.cache[start] = data, end
            else:
                self.cache[start] = self.file.buffer[start:end], end
        return self.cache[start]


class VorbisThread(SoundThread):

    def __init__(self, vorbis, callback):
        self.vorbis = vorbis
        self.paused = Event()
        super().__init__(callback)

    def rebegin(self):
        self.paused.set()
        if self.active:
            self.end()
            # sleep しないと曲の先頭に戻らないことがある
            time.sleep(0.1)
        self.begin()

    def play(self):
        self.paused.set()
        self.open(self.vorbis.format, self.vorbis.file.channels,
                  self.vorbis.file.frequency)
        start = 0
        while self.active:
            data, start = self.vorbis.getdata(start) 
            self.stream.write(data)
            self.paused.wait()
            if start < 0:
                self.end()
        self.close()


class VorbisPlayer(Player):

    def __init__(self, chunk = 1024, loop = 1, tagloop = 1,
                 enabled = 1):
        super().__init__(enabled)
        self.__chunk = chunk
        self.__vorbises = {}
        self.__thread = 0
        self.__loop = loop        # True で loop する
        self.__tagloop = tagloop  # True で LOOPSTART & LOOPLENGTH を使う

    def off(self):
        super().off()
        self.stop()

    def play(self, ogg, callback = 0):
        if not self.is_enabled():
            return
        if ogg in self.__vorbises:
            v = self.__vorbises[ogg]
        else:
            v = Vorbis(ogg, self.__chunk, self.__loop, self.__tagloop)
            self.__vorbises[ogg] = v
        if self.__thread:
            self.__thread.vorbis = v
            self.__thread.callback = 0
            self.__thread.rebegin()
            self.__thread.callback = callback
        else:
            self.__thread = VorbisThread(v, callback)

    def stop(self):
        if self.__thread and self.__thread.active:
            self.__thread.end()

    def pause(self):
        if not self.is_enabled():
            return
        if self.__thread:
            self.__thread.paused.clear()

    def resume(self):
        if not self.is_enabled():
            return
        if self.__thread:
            self.__thread.paused.set()




'''
waveplayer.py  v1.4

Copyright (c) 2020 Takenoko (http://nekokiss.seesaa.net/)
Released under the MIT license.
see https://opensource.org/licenses/MIT

PyAudio が install されている必要があります.
'''

from threading import Event

import pyaudio as pa
import wave

from .soundthread import SoundThread
from .player import Player

class Wave:

    def __init__(self, wav, chunk):
        self.file = wav
        with wave.open(wav, 'rb') as wf:
            self.format = pa.get_format_from_width(wf.getsampwidth())
            self.channels = wf.getnchannels()
            self.rate = wf.getframerate()
            self.buffer = []
            while 1:
                data = wf.readframes(chunk)
                if len(data) <= 0:
                    break
                self.buffer.append(data)


class WavThread(SoundThread):

    def __init__(self, wp, wav, callback):
        self.wp = wp
        self.wav = wav
        super().__init__(callback)

    def close(self):
        super().close()
        self.wp._WavePlayer__blocked.set()

    def play(self):
        self.open(self.wav.format, self.wav.channels,
                  self.wav.rate)
        for data in self.wav.buffer:
            if self.active:
                self.stream.write(data)
        if self.active:
            self.end()
        self.close()


class WavePlayer(Player):

    def __init__(self, chunk = 1024, maxthreads = 8, enabled = 1):
        super().__init__(enabled)
        self.__chunk = chunk
        self.__waves = {}
        self.__threads = []
        self.__blocked = Event()
        if maxthreads < 1:
            maxthreads = 1
        self.__maxthreads = maxthreads  # 最大同時再生 Thread 数

    def __getwav(self, wav):
        if wav not in self.__waves:
            self.__waves[wav] = Wave(wav, self.__chunk)
        return self.__waves[wav]

    def off(self):
        super().off()
        self.stopall()

    def getmaxthreads(self):
        return self.__maxthreads

    def setmaxthreads(self, v):
        if v < 1:
            return
        over = min(self.__maxthreads, len(self.__threads)) - v
        if over > 0:
            for i in range(over):
                t = self.__threads.pop(0)
                if t.active:
                    t.end()
                self.__threads.append(t)
        self.__maxthreads = v

    def play(self, wav, block = 0, callback = 0):
        if not self.is_enabled():
            return
        if block:
            self.__blocked.clear()
        for i, t in enumerate(self.__threads):
            if i < self.__maxthreads:
                if not t.active:
                    t.wav = self.__getwav(wav)
                    t.callback = callback
                    t.begin()
                    break
        else:
            if len(self.__threads) >= self.__maxthreads:
                t = self.__threads.pop(0)
                t.end()
                t.wav = self.__getwav(wav)
                t.callback = callback
                t.begin()
            else:
                t = WavThread(self, self.__getwav(wav), callback)
            self.__threads.append(t)
        if block:
            self.__blocked.wait()

    def stop(wav):
        for t in self.__threads:
            if t.wav.file == wav and t.active:
                t.end()
                return 1
        return 0

    def stopall(self):
        for t in self.__threads:
            if t.active:
                t.end()



vwp200727.zip

スレッドについて, 少しだけわかった気がします.

20/07/27 追記

ファイルを差し替えました. 更新履歴を, ソースコードではなく update.txt にまとめただけですが. あと, この記事にコードを貼り付けました. コードに問題があった場合, 指摘して頂けるとありがたいです.

20/07/28 追記

説明文を追加.

ラベル:Python download
posted by Takenoko at 09:42| Comment(0) | programming | このブログの読者になる | 更新情報をチェックする

2020年07月09日

Python 3 で, Ogg Vorbis と Wave を再生する Player を書きました

タイトルの通りです. ゲーム制作で必要だったので書きました. ゲームでよく使われるのは .ogg (Ogg Vorbis) と .wav だと思うので, それらを再生できます. ogg は, LOOPSTART, LOOPLENGTH に対応しています.

PyAudio, PyOgg, audio-metadata を使用しているので, それらの install が必要です.

vorbisplayer.py で import している audio-metadata が, Python 3.6 以降を要求するので, それ以降の Python で動きます. waveplayer.py だけを使うのであれば, それ以下でも動くはずです.

ソースファイル (vwp1.1.zip) のダウンロード

zip 内の readme.txt, sample.py を読むと, 使い方がわかると思います.

Linux Mint 18.3 & Python 3.6.11, Windows 8.1 & Python 3.6.8 で動作しました. Mac は持っていないのでわかりません.

何か間違い等があった場合, 指摘していただけるとありがたいです.

20/07/12 追記

ファイルを Version 1.1 に差し替えました.
vorbisplayer に, pause と resume を実装する等の変更を行いました.

20/07/26 追記

続き を書きました. ファイルも次の記事にあります.

ラベル:Python download
posted by Takenoko at 20:52| Comment(0) | programming | このブログの読者になる | 更新情報をチェックする

2019年12月17日

Kivy アプリの Windows 用実行ファイルを作成するまで (ライセンス編)

nuitka で kivy 製アプリの実行ファイルを作製した際, *.dist ディレクトリに自動的に生成される dll, 及び, Python*\share\glew\bin\, Python*\share\sdl2\bin\ 両ディレクトリに存在する dll のライセンスについてのメモです. 正確でない可能性は大いにあります. 正直, わからないことが多いので, 間違い等を指摘していただけるとありがたいです.

  • comctl32.dll
    役割: Windows のコモンコントロールを呼び出すための dll ?
    ライセンス: 不明. Visual C++ 6.0 再頒布可能パッケージに含まれているので, 同梱しても問題ない?
    参考:
    https://www.ipentec.com/document/visual-studio-c-plus-plus-redistribution-files
    http://chokuto.ifdef.jp/urawaza/comctl.html

  • libcrypto-1_1.dll, libssl-1_1.dll
    役割: OpenSSL "インターネットでの暗号化通信に使われるオープンソースのプログラムやソフトウェアのこと。"
    ライセンス: OpenSSL License
    引用: https://www.kddi.com/yogo/セキュリティ/OpenSSL.html
    参考: https://ja.wikipedia.org/wiki/OpenSSL
    https://www.atmarkit.co.jp/ait/articles/0906/26/news129_2.html

  • python37.dll
    役割: Python 3.7 を利用するための dll ?
    ライセンス: Python Software Foundation License
    参考:
    https://ja.wikipedia.org/wiki/Python_Software_Foundation_License
    https://docs.python.org/ja/3/faq/general.html

  • pywintypes37.dll
    ライセンス: python37.dll と同じ?

  • sqlite3.dll
    役割: "SQLite(エスキューライト、エスキューエライト)は、パブリックドメインの軽量な関係データベース管理システム (RDBMS) である。"
    ライセンス: public domain
    引用: https://ja.wikipedia.org/wiki/SQLite

  • tcl86t.dll, tk86t.dll
    役割: おそらく, tcl/tk を使用するための dll
    ライセンス: BSDライセンス ?

  • vcruntime140.dll
    役割: C で作製された exe を起動するのに必要な dll ?
    ライセンス: 不明. Visual Studio 2015 の Visual C++ 再頒布可能パッケージに含まれているので, 同梱しても問題ない?
    参考: https://www.ipentec.com/document/visual-studio-c-plus-plus-redistribution-files

  • glew32.dll
    役割: OpenGL Extension Wrangler Library
    ライセンス: Modified BSD License, MIT License

  • SDL2.dll, SDL2_image.dll, SDL2_mixer.dll, SDL2_ttf.dll
    ライセンス: zlib License

  • libFLAC-8.dll
    役割: "FLAC(フラック、Free Lossless Audio Codec)は、オープンフォーマットの可逆圧縮音声ファイルフォーマットである。"
    ライセンス: 修正BSDライセンス・三条項BSDライセンス
    引用: https://ja.wikipedia.org/wiki/FLAC

  • libfreetype-6.dll
    役割: "FreeType(フリータイプ)は、フォントエンジンを実装したライブラリである。"
    ライセンス: The FreeType Project LICENSE
    引用: https://ja.wikipedia.org/wiki/FreeType
    参考: http://giraffydev.hatenablog.com/entry/2016/09/27/101841

  • libjpeg-9.dll
    役割: "libjpegは、JPEGのエンコード、デコードを行うためのライブラリである。JPEGファイルを操作するためのユーティリティも含んでいる。"
    ライセンス: フリー、ロイヤリティ無しで商用利用可、表示が必要。"this software is based in part on the work of the Independent JPEG Group" と表記すればよい?
    引用: https://ja.wikipedia.org/wiki/Libjpeg
    参考: https://qa.itmedia.co.jp/qa5192199.html

  • libmodplug-1.dll
    役割: "ModPlug Tracker(モッドプラグトラッカー)は、Windows上で Olivier Lapicque によって開発されたオーディオモジュールトラッカーである。"
    ライセンス: public domain

  • libmpg123-0.dll
    役割: mpg123 "mpg123 is a free and open-source audio player. It supports MPEG audio formats, including MP3."
    ライセンス: LGPL 2.1
    引用: https://en.wikipedia.org/wiki/Mpg123

  • libogg-0.dll
    ライセンス: 修正BSDライセンス・三条項BSDライセンス

  • libopus-0.dll
    ライセンス: 修正BSDライセンス・三条項BSDライセンス

  • libopusfile-0.dll
    ライセンス: 修正BSDライセンス・三条項BSDライセンス

  • libtiff-5.dll
    ライセンス: libtiff Software License

  • libwebp-7.dll
    ライセンス: 修正BSDライセンス・三条項BSDライセンス

  • libvorbis-0.dll
    ライセンス: 修正BSDライセンス・三条項BSDライセンス

  • libvorbisfile-3.dll
    ライセンス: 不明. libvorbis-0.dll と同じだろうか

  • zlib1.dll
    ライセンス: zlib License

気をつける必要がある dll は, LGPL 2.1 ライセンスの libmpg123-0.dll 位でしょうか. このファイルは (おそらく, 動画を扱わなければ) 無くても動くので, nuitka で生成したファイル群を, ソースファイルを公開せずに頒布しても問題なさそうに思えます.

ラベル:Windows nuitka kivy Python
posted by Takenoko at 11:16| Comment(0) | programming | このブログの読者になる | 更新情報をチェックする

2019年11月19日

Kivy アプリの Windows 用実行ファイルを作成するまで (作製編)

1. PyInstaller を使用する場合

main.py

main.kv

上記の main.py, main.kv を例に説明します. 適当なディレクトリにこれらのファイルを作製します.

コマンドプロンプトを管理者として開き, main.py ファイルのあるディレクトリに移動し,

python -m PyInstaller --noconsole main.py

を入力します.

main.py のあるディレクトリに生成された main.spec を開き,

# -*- mode: python ; coding: utf-8 -*-

の次の行に,

from kivy_deps import sdl2, glew

を追加し, ('.' ではなく, '_' なので注意*1)

a.datas,

の次の行に,

*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],

を追加します. インデントは揃えます.

datas=[],

datas=[('main.kv', '.')],

にします. kv ファイルを使わない場合は, 必要ないはずです.

python -m PyInstaller main.spec

と入力し,

WARNING: The output directory "(main.py のあるディレクトリ)\dist\main" and ALL ITS CONTENTS wil l be REMOVED! Continue? (y/N)

と出たら y を入力します.

dist/main

に main.exe が作製されているので, 実行して画面が表示されたら成功です.

2. Nuitka を使用する場合

main.py

上記の main.py (main.kv は PyInstaller の項と同じもの) を例に説明します. 適当なディレクトリにこれらのファイルを作製します.

コマンドプロンプトを管理者として開き, main.py ファイルのあるディレクトリに移動し,

python -m nuitka --standalone --windows-disable-console --mingw64 --jobs=1 main.py

と入力します. jobs は, CPU コア数 * 2 にするといいのかもしれません. この作業は時間がかかります. 終了後, main.dist/ に main.exe が作製されます.

Python37-32\Lib\site-packages\kivy\

から data フォルダを main.dist/kivy にコピーし,

Python37-32\share\glew\bin\

から glew32.dll を,

Python37-32\share\sdl2\bin\

から全てのファイルを main.dist にコピーします. *2 最後に, main.kv を main.dist にコピーします.

main.exe を実行して画面が表示されたら成功です.

3. サンプル

以前, Python で迷路生成 で書いた kivy のコードを PyInstaller, Nuitka の両方で exe 化してみました.

PyInstaller

Nuitka

自分の環境では動作する, しないといった報告をしていただけると喜びます. 少なくとも, Linux Mint 18.3 の Wine では動きませんでした.

*1

Create a package for Windows(翻訳済み) − Kivy 1.10.0 ドキュメント:

では kivy.deps になっている. 以前はそうだったのかもしれない.

*2

作製環境でこのサンプルを動かした場合,

  • libmpg123-0.dll
  • libcrypto-1_1.dll
  • libssl-1_1.dll
  • libvorbis-0.dll
  • libvorbisfile-3.dll
  • libwebp-7.dll
  • libtiff-5.dll
  • libopus-0.dll
  • libopusfile-0.dll
  • libmodplug-1.dll
  • libFLAC-8.dll
  • libogg-0.dll
  • tcl86t.dll
  • tk86t.dll
  • sqlite3.dll
は無くても動きました.

参考ページ

Create a package for Windows(翻訳済み) − Kivy 1.10.0 ドキュメント:
KivyのGUIアプリをNuitkaで簡単に小サイズ・高速に動く実行ファイル(exe)にする(Windows10)
Packaging Kivy apps written in Python 3, targeting Windows using Nuitka

19/12/17 追記: 無くても動く dll を列挙した.

posted by Takenoko at 13:40| Comment(0) | programming | このブログの読者になる | 更新情報をチェックする

Kivy アプリの Windows 用実行ファイルを作成するまで (準備編)

windows 8.1 Home 64bit で, Python がインストールされていない windows でも 実行できる Kivy アプリの exe を作製するまでの過程です.

長くなったので, Python, gcc 等をインストールする準備編, PyInstaller or Nuitka を使用する作製編に分割しました. 後日, ライセンス編も書く予定です.

私の場合, 作成したファイルをネットで公開するつもりなので, Python や gcc 等は 32bit を選択しています. ファイルのバージョンは, メモを書いていた時点での最新を選んでいます.

1. mingw-w64 32bit インストール

http://mingw-w64.org/doku.php/download/mingw-builds

で, Installation: Sourceforge をクリックするとページ遷移し, インストーラが自動的にダウンロードされます.

mingw-w64-install.exe

を実行し,

Ver 8.10
i686
posix
sjlj
0

を選択します.

デフォルトのインストールパスが長いので,

C:\mingw-w64\i686-8.1.0-posix-sjlj-rt_v6-rev0

に変更します.

環境変数の Path に

C:\mingw-w64\i686-8.1.0-posix-sjlj-rt_v6-rev0\mingw32\bin\

を追加します.

コマンドプロンプトを開き,

gcc -v

と入力し, いろいろと情報が出てきたら成功です.

2. Python3 32bit をインストール

https://www.python.org/downloads/windows/

から, Stable Releases の, Nuitka が対応している最新バージョン (現時点では 3.7.5) の Download Windows x86 executable installer をクリックしてインストーラをダウンロードします.

python-3.7.5.exe

を実行します.

Add Python 3.7 to PATH にチェックを入れ, Install Now をクリックします. Path は自動的に追加されるようです.

3. Kivy をインストール

コマンドプロンプトを管理者として開き, 以下の, '#' でコメントアウトしていない行を順に入力します.

python -m pip install --upgrade pip wheel setuptools
python -m pip install docutils pygments pypiwin32 kivy.deps.sdl2 kivy.deps.glew
#python -m pip install kivy.deps.gstreamer
#python -m pip install kivy.deps.angle
python -m pip install kivy

インストールが終わったら,

pip list

と入力し, Kivy がインストールされていることを確認します.

*コメントアウトした行について

#python -m pip install kivy.deps.gstreamer

Kivyを使い始める

には, "Kivyには既にオーディオとビデオのプロバイダがありますが、より高度なものにはGStreamerが必要です。" と書いてあります. また, 動画プレイヤーも入っているらしいです. 私には必要なさそうなので入れませんでした.

#python -m pip install kivy.deps.angle

Kivy Windows Hello Worldへの道 真っ黒画面

には, "OpenGl ESのDirectX実装" と書いてあります. 必要かどうかわからないので, 必要になった時点で入れれば良いのだろうと思います.

4. Kivy のエラー対策

Windows で kv ファイルを読み込む際にエラーが出るようなので,

C:\Users\ユーザー名\AppData\Local\Programs\Python\Python37-32\Lib\site-packages\kivy\lang\

の (環境やバージョンによって場所は違うはず) builder.py を変更します.

if __debug__:
trace('Lang: load file %s' % filename)
with open(filename, 'r') as fd:
kwargs['filename'] = filename
data = fd.read()

with open(filename, 'r') as fd:

with open(filename, 'r', encoding='utf8') as fd:

に書き換えます.

5. PyInstaller をインストール (使用する場合)

python -m pip install pyinstaller

と入力し, 終了後,

pip list

と入力し, インストールされていることを確認します.

6. Nuitka をインストール (使用する場合)

python -m pip install nuitka

と入力し, 終了後,

pip list

と入力し, インストールされていることを確認します.

作製編 へ続きます.

posted by Takenoko at 12:48| Comment(0) | programming | このブログの読者になる | 更新情報をチェックする

2019年09月06日

JNetHack ゲヘナ

ゲヘナまでやってきた.

jnhfillice.png
jnhfillfire.png

パッチを自作して, ゲヘナの迷路をこういうランダムマップで置き換えています. JSporkHack のスクリーンショットに影響されました. あの迷路, 正直, 退屈だなあと, 20 年程思い続けていました.

jnhinv.png

ちょっと準備しすぎた.

jnhorcus.png

虐殺の巻物は, 呪われたもの以外は, m に対してのみ使うことにしています. 店に出現できなくなるため, その分アイテムが増えます.

ラベル:Roguelike nethack
posted by Takenoko at 11:49| Comment(0) | game | このブログの読者になる | 更新情報をチェックする

2019年09月01日

JNetHack TNG Patch 用 Patch 1.30

JNetHack TNG Patch 用 Patch の Version 1.20 です. 以下の修正を行います.

1. reject された噂を追加
2. ショッカーの効果が機能するように
3. ショッカー使用時のメッセージを追加
4. 力の杖の SPFX_TOUCH が機能するように
5. 力の杖に SPFX_NOGEN フラグを追加
6. ムーマクベーンが巨大ムーマクにも効くように
7. ムーマク, 巨大ムーマクの色を白に変更
8. ガラスの指輪の素材を IRON から GLASS に変更
9. ローグレベルのモンスターの G_GENO フラグを除去, M2_NOPOLY フラグを追加
10. TNG の追加ユニークに M2_NOPOLY フラグを追加

ローグレベルのモンスターやユニークモンスターが変化によって出現してしまうことがあったため, それを防ぐための修正などを行いました. 多分防げていると思います.

ファイル ダウンロード

使い方は, JNetHack3.4.3-0.11 に TNG 最新安定版 Patch を当てた後,
$ bzcat ../jnh3.4.3-0.11-tng-fix-v130.patch.bz2 | patch -p1
と入力するだけです. テスト版に適用できるかどうかはわかりません.

余談ですが, 私が遊んでいたオリジナルの TNG のバージョンは, ローグレベルのモンスターが通常のレベルに出現することがよくあり, ノームの鉱山で翼ライオンによく殺されたものです.

ラベル:nethack Roguelike
posted by Takenoko at 21:39| Comment(0) | game | このブログの読者になる | 更新情報をチェックする

2019年08月31日

JNetHack 3.4.3 魔法防御, ドレイン耐性, 騎乗スキル上昇

JNetHack 3.4.3 のソースを読んでわかった事を自分用にメモ. 昔ネットにあったスポイラーは, だいぶ少なくなってしまったし. C 言語は全く自信がない. 読み間違いがあるかもしれない.

src/monst.c
攻撃属性に AD_MAGM (魔法の矢) がある場合 (灰色ドラゴン, 天使, 賢者, イーノグ), 灰色ドラゴンの子供である場合, 攻撃属性に AD_RBRE (ランダムブレス) がある場合 (クロマティック・ドラゴン) は, 魔法防御を持つ.

src/monst.c
アンデッド, 悪魔, 獣人, デスはドレイン耐性を持つ.

src/hack.c から呼ばれている, src/steed.c の exercise_steed
騎乗した状態で移動するごとに, urideturns に +1 される. 待機では上昇しない. urideturns が 100 以上になった際に 騎乗スキル経験値に +1 され, urideturns が 0 になる. 降りたりしても, urideturns が減ることはない.

ラベル:Roguelike nethack
posted by Takenoko at 12:31| Comment(0) | game | このブログの読者になる | 更新情報をチェックする

2019年08月23日

JNetHack フォント変更 スクリーンショット

jnhgnome.png

NetHack tty TrueType Tile Font で公開されているフォントに変更してみました. "{" と "}" のような, 一見で見分けづらいシンボルが見やすくなるし, なにより美しい. すばらしい. 私は, NPC だけはアルファベットで表示しています. そのほうがわかりやすい.

jnhmumak.png

ムーマクやばい. イメージほど遅くないし.


この表示だと, htmldump で出力した map がまともに表示されない. 一旦ゲームを終了し, フォントを戻して出力すると, 問題はなかった.

19/08/24 追記 文章を修正.
ラベル:Roguelike nethack
posted by Takenoko at 15:39| Comment(0) | game | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は180日以上新しい記事の投稿がないブログに表示されております。