2023年2月23日木曜日

10万遠征成功達成

 99999…

10万!

1年に1万回ですかい…1日平均27回とか言う恐ろしい数字が出てくるのですが…。
それと、10年で失敗が259回ってのも地味にすごい数字ですね。ちなみに演習219敗は主に1年目に敗北必至で演習していた為です…現在でも稀に1日に2、3敗する事があるのですが。
さて、現在の資材はこんな感じであり、どう見ても来週からイベントを始める状況ではありません。

  • むりやり手に入れた最上瑞雲ですが…
コレは辛かったですね。あらかじめ★1の瑞雲改二を持っていたとはいえ、その後にネジ40個と瑞雲13個が必要になります。
ただ、この夜戦瑞雲、確かに最上に載せるとパラメータ上強いのですが、機数が少なすぎるので、本領を発揮するのは大和改二重ではないかと思います。
又、近年やたらと夜戦を推すので恐らく大規模な払暁戦イベントを仕掛けてくるのではないかと予想しています。
アニメで言ったら3話までの話であり、ゲームなら1期最後のレイテ前編(2017年秋イベ)の最終マップ辺りで過去にやっていました。

夜戦になるならばと、瑞鳳改二乙の量産や赤加賀の増産をした為資材が尽きています。
現在の運営の更新速度から考えると、まだ見ぬ新艦や改二の為に資材を貯めこむよりも、現有戦力でラストスパートをかける時と判断しています。

  • 次のイベントの新艦は恐らく夕暮と…
多分、コレのモチーフ元。陸軍娘は毎度絵師が変わるので誰が担当かは解りませんが特設空母…うーん低速軽空母ですら戦力として微妙なんですが…
実態としては、クエストに実装する度に苦情が出る6-4右回りの特化空母なんじゃないかな?という気がします。

2023年2月20日月曜日

買い物小話

 以前「アッシュアームズはキャラは良いからゲームは再開しないけど書籍が出たら買う」とか書いていましたが、出てたんですね…。BOOTH で出品されている上に届くまで2ヶ月もかかる事から中国で作って船便なんでしょうけど、ひとまず予約しました。

  • トライポッドワークスのC109Sに続いて、何年か前に買った MacBookAir のパチモノのバッテリーが案の定壊れまして
寝床で使えるPCがなくなりました(流石に13インチオーバーのノートはでかいし、中華パッド系はキーボードが…)。そこで、あきばおーで売っている7インチモニタと小型キーボードを購入、以前組んだエプソンエンデバー2台をKVMに繋いだ物と接続して使うことに。
で、それ自体はなんとか動いたのですが(流石に Atom270 の方はかなり厳しい)ふと、この7インチモニターには HDMI コネクタがついているなと。
…ついているということは、スティックPCを接続すれば一体型PCになるのでは…
…と、思ったのですが、結局タッチできない中華パッドになると気づいて正気に戻りました。稼働できる中華パッドを3台以上も持っていて考える事じゃないですね。
クロームキャストとつないで、小型ドンキTV(所謂NHKの映らないTV)として使用するという手もあるかもしれませんが。

  • 最近SSDの値段が落ちてきていまして
1TBも1万円を切っています。私は15年ほど前にキューブPCで Win2000 を使っていたのですが、そのときに最後に1TBのHDDに換装してしまったのですよね。
おかげで移植ができなかったのですが、やっとSSDに移植できます。
ついでに、休眠中のMACにでも入れてみますか…CoreDuo と PentiumM のどちらが早いのか見当が付きませんが。
中に入っているゲームが遊べるかぐらいしか興味がないので、いっそ3世代 Core i5 の∪型が乗っている、レッツノートに移植するのも手かもしれません。
おそらく、2000 年代初頭の AGP 接続ビデオボードの性能くらいなら iGPU で超えるのではないでしょうか?

  • 不調の Yoga260 ですが
昨年末にメモリを変えても結局不調だった Yoga260 なのですが、それならマザーボードを交換してみたらどうだろう?と考えた訳ですよ。
アリババで調べた所、Corei7 でメモリがオンボードで8GB乗っている物が売られていました。コレならば i5 からコア数が倍になる上に、メモリもデュアルチャンネルにできそうです。
…が、良く調べたら、現在中古市場に Yoga380 や Yoga720 等の上位機種がかなりの安値で流れているのですよね。アリババだと当然中国からの船便で2ヶ月待ちになりますし、これは流石に要らないかもしれません。

2023年2月7日火曜日

Python+Kivy 備忘録 BMPファイルを読んでみる編

はい、前回テキストを読みましたが、今回はBMPファイルです。
といっても処理を簡単にしたかったので、24ビットBMPファイルしか読めません。

## load_bmp ##

from kivy.app import App
from kivy.uix.widget import Widget

from kivy.graphics import Color, Ellipse, Line, Rectangle
from kivy.core.window import Window

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput

from kivy.uix.floatlayout import FloatLayout
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup

import os
from os.path import join,isdir
import uuid
from datetime import datetime

from kivy.uix.filechooser import FileChooserIconView
from kivy.uix.filechooser import FileChooserListView

from kivy.clock import Clock

Window.clearcolor = (0,0,0,0)

class BtnChangeSelectFile(Button):
    def on_release(self):
        self.parent.DrawSelectFile()
        
class BtnSelectFile(Button):
    def on_release(self):
        self.parent.parent.lFile.text='\n'.join(self.parent.fc.selection)
        self.parent.DrawBase()
        
class BtnChangeBase(Button):
    def on_release(self):
        self.parent.DrawBase()

class RGB():
    def __init__(self,r,g,b):
        self.r = r
        self.g = g
        self.b = b
        
class Output(BoxLayout):
    def __init__(self,path,**kwargs):
        super(Output,self).__init__(**kwargs)

        outputtext = path
        header = []
        
        self.map_width = 0
        self.map_height = 0
        self.bitmap:RGB = []

        self.list_la =[]
        self.list_rc =[]

        while True :
            if not os.path.exists(path):
                break
            outputtext = "exists"
            
            size = os.path.getsize(path)
            if size < 54:
                outputtext = "header not found"
                break
                
                
            with open(path,'rb') as f: 
                while True :
                    header = f.read(54)
                    
                    if not ((header[0]==66)&(header[1]==77)):
                        outputtext = "this file is not bmp"
                        break
                    
                    filesize = int(header[2]+(header[3]<<8)+(header[4]<<16)+(header[5]<<24))
                    headersize = int(header[10]+(header[11]<<8)+(header[12]<<16)+(header[13]<<24))
                    colorbit = int(header[28]+(header[29]<<8))
                    w = int(header[18]+(header[19]<<8)+(header[20]<<16)+(header[21]<<24))
                    h = int(header[22]+(header[23]<<8)+(header[24]<<16)+(header[25]<<24))
                    
                    if headersize != 54:
                        outputtext = "this format not surpported"
                        break
                        
                    if colorbit != 24:
                        outputtext = "24 bit color only"
                        break
                        
                    ### read bitmap ###
                    hsize = int((filesize - headersize)/h)
                    d = f.read(filesize - headersize)
                    
                    for y in range(h):
                        for x in range(w):
                            idx = hsize * y + x * 3
                            self.bitmap.append(RGB(b = int(d[idx+0]),g = int(d[idx+1]),r = int(d[idx+2])))
                            
                    outputtext ="colorbit:"+str(colorbit)+"width:"+str(w)+"/height:"+str(h)
                    self.map_width = w
                    self.map_height = h

                    break
            break
        print(outputtext)
        self.text = outputtext

    def Draw(self):
        if not self.bitmap:
            return
            
        with self.canvas.before:
            # clear all rectangle
            for old in self.list_rc:
                self.canvas.before.children.remove(old)
            self.list_rc.clear()
            
            # clear all label
            for old in self.list_la:
                self.canvas.before.children.remove(old.canvas)
            self.list_la.clear()
            
            w = self.size[0]/self.map_width
            h = self.size[1]/self.map_height
            idx = 0
            for y in range(int(self.map_height)):
                for x in range(int(self.map_width)):
                    Color(self.bitmap[idx].r/255,self.bitmap[idx].g/255,self.bitmap[idx].b/255)
                    idx = idx+1
                    self.list_rc.append(Rectangle(pos=(self.right-self.size[0]+x*w,self.top-self.size[1]+y*h),size=(w,h)))

class SubDisplay(BoxLayout):
    def __init__(self,**kwargs):
        super(SubDisplay,self).__init__(**kwargs)
        self.fc=FileChooserListView()
        #self.fc=FileChooserIconView()
        self.fc.size_hint_y=7
        self.fc.filters=['*.bmp']
        self.mode = -1 # setup

        Clock.schedule_interval(self.update, 1.0/3.0)

    def update(self,dt):
        if self.mode == 0: # Base Mode
            self.main_disp.Draw()
            return
        
    def DrawBase(self):
        self.clear_widgets()
        self.orientation='vertical'
        
        self.main_disp =Output(path=self.parent.lFile.text,size_hint_y=4)
        b1 =BtnChangeSelectFile(text='SelectFile',size_hint_y=1)
        self.add_widget(self.main_disp)
        self.add_widget(b1)
        
        self.mode = 0 # Base
        
    def DrawSelectFile(self):
        self.clear_widgets()
        self.orientation='vertical'

        b2=BtnSelectFile(text='SelectFile',size_hint_y=1)
        b3=BtnChangeBase(text='QUIT',size_hint_y=1)
        
        self.add_widget(self.fc)
        self.add_widget(b2)
        self.add_widget(b3)
        
        self.mode = 1 # Select

class Display(BoxLayout):
    orientation='vertical'
    def __init__(self,**kwargs):
        super(Display,self).__init__(**kwargs)
        self.lFile = Label(text='No Selected',size_hint_y=1)
        self.boxSub = SubDisplay(size_hint_y=8)
        self.add_widget(self.lFile)
        self.add_widget(self.boxSub)
        self.boxSub.DrawBase()
        
class LoadBmpApp(App):
    def build(self):
        layout = Display()
        return layout

if __name__=='__main__':
    LoadBmpApp().run()

※毎度の事ですが、一部字を小さくしているので、コードはコピペして読む事を推奨します

  • キモは BoxLayout 派生クラスの Output クラス
解説するとしたらイニシャライズで行っている、BMPファイルの読み込みと Draw 関数でしょうか。
そこまで怪しい処理は組んでいないと思いますが、いくつか注意点を連ねます。

  •  hsize という変数はビットマップの横一列分のデータサイズです
ビットマップは横一列のデータサイズが4バイト区切りで無いといけないというルールがあります。しかし、24ビット=3バイトで1ドットを表現している都合上、画像サイズによっては4で割り切れない場合があります。
この場合、末端に穴埋め用のデータを詰めて4バイトで割れるように整えます(パディングとか言います)。
が、この計算が面倒だったので、単純に画像データサイズ(ファイルサイズ-ヘッダーサイズ)をビットマップの縦のドット数で割って求めています。

  • 各ドットの色の順
一般的に光の三原色はRGBと並べますが、ファイルにはBGRの順に並んで格納されているので取り出す際に注意が必要です。

  • 描画は1秒間に3回行っている
Output クラスの Draw メソッドは親の SubDisplay クラスから1/3秒ごとに呼ばれる事になっています。
これは add_widget 直後ではサイズが定かではない為、正しく描画ができなかった為です。

…で、動かしてみたのですが…
…動く…けど、無茶苦茶重い。
32x32ドットの画を1024個の Rectangle で秒間3回描画しているだけなのに異常に重い。
コレはなにかしらやらかしている予感がしますね。
本当は次はテクスチャフォーマットの読み込みをやりたかったのですが、改良編になりそうです。

2023年2月1日水曜日

14回目のランクイン


…うーん。
ひとまずあきつ丸に装備させてみるとこんな感じ。
アタリかハズレかは微妙過ぎて論じませんが…
コレ、水母と揚陸艇の装備なんですよねえ。前回の奴も航空巡洋艦用の水戦でしたし。
つまり

空母出禁にしときました、敵側は航空戦力と潜水艦でしこたま殴りますので、空母以外で防空してね

…という、日本の末期をモチーフにしたイベントを今後もやりたいんだろうなあ…といった感想が真っ先にでますね。

アニメに出た艦隊編成が信濃の護衛についた艦が多いとのコメントをどこかで見ましたが、次期イベントの新規追加はとりあえず1艦は陸軍の揚陸艇っぽいですし、51センチ砲等のそれらしい先行装備の配布が無いので…また、空襲と潜水艦の攻撃の中を空母無しで延々と輸送を続ける苦行になる上で、大型艦追加無しというオチがつくのではないかと思われます。
いい加減テコ入れが必要なタイミングだと思うのですけどね。