Tilekartta editori Coolbasicilla

Voit pyytää apua ohjelmointiongelmiin täältä.
MrMonday
Advanced Member
Posts: 378
Joined: Fri Oct 10, 2008 2:35 pm

Re: Tilekartta editori Coolbasicilla

Post by MrMonday » Fri Jul 27, 2012 4:56 pm

Moi, en viitsinyt aloittaa uutta ketjua, koska tämä ongelma periaatteessa liittyy tämän ketjun aiheeseen. Olen nimittäin tekemässä tiedostohakemistoa tai hakemistopuuta tai miksikä sitä nyt sitten kutsutaankaan, enkä osaa itse ratkaista, että miten saisin tiedostot näkymään oikein hakemistossa, ettei sinne tulisi ylimääräisiä "." ja ".." kansioita. Ja itse koodi:

Code: Select all

SCREEN 800,600

dir_img = LoadImage("directory_img.png")

Type FILES
    Field Name$
    Field Dir
EndType

    StartSearch
        Repeat
    
        File.FILES  = New(FILES)
        File\Name$  = FindFile()
        File\Dir    = IsDirectory(File\Name$)
        
        If File\Name$ <> "" Then 
            i = 1
        Else
            i = 0
        EndIf
    
        Until i = 0
    EndSearch


Repeat

    Y = 0
        
    File.FILES = First(FILES)
        
    While File <> NULL

        If File\Dir = 1 Then DrawImage dir_img,0,y
        
        If TextButton(ImageWidth(dir_img),y,File\Name$) And File\Dir = 1 And MouseHit(1)
            ChDir File\Name$
            Gosub Refresh_list
        ElseIf MouseHit(2)
            ChDir ".."
            Gosub Refresh_list
        EndIf
        
        y = y + TextHeight(File\Name$)
        
        File = After(File)
        
    Wend

    DrawScreen
    
Until KeyHit(1)

Refresh_list:
    
    While File <> NULL
        Delete File 
        File = After(File)
    Wend
    
    StartSearch
        Repeat
    
        File.FILES  = New(FILES)
        File\Name$  = FindFile()
        File\Dir    = IsDirectory(File\Name$)

        If File\Name$ <> "" Then 
            i = 1
        Else
            i = 0
        EndIf
    
        Until i = 0
    EndSearch

Return

Function TextButton(x,y,txt$)
    If MouseX()>x And MouseX()< x+TextWidth(txt$) And MouseY()>y And MouseY()< y+TextHeight(txt$)
        Color 255,0,0
        Text x,y,txt$
        Return 1
    Else
        Color 255,255,255
        Text x,y,txt$
        Return 0
    EndIf
EndFunction

Eli luodaan tyyppi "FILES" jossa on kentät "Name$", johon tallennetaan kansion/tiedoston nimi ja "Dir", jossa on tieto siitä, onko kyseinen "tiedosto" kansio. Sitten plärätään kerran nykyisen sijainnin sisältämät tiedostot ja kansiot ja tulostetaan ne näytölle. Pääsilmukassa nykyinen sijainti päivitetään ja mikäli hiiri on kansion päällä ja klikataan vasenta hiiren painiketta, niin siirrytään kansioon, ja käydään päivittämässä lista. Olihan tarpeeksi epäselvä selostus?

Niin, ja kansio kuva, jos ette itse jaksa piirrellä:
directory_img.png
kansio
directory_img.png (177 Bytes) Viewed 6015 times
EDIT:

Niin ja hiiren oikea painike tuo "pykälän" ylöspäin hakemistossa.


User avatar
Jonez
Devoted Member
Posts: 575
Joined: Mon Aug 27, 2007 8:37 pm

Re: Tilekartta editori Coolbasicilla

Post by Jonez » Fri Jul 27, 2012 5:50 pm

En nyt jaksanut ladata kuvaa ja testata koodia, mutta tässä pari ideaa:

Itse kysymykseen: tarkasta ennen itse kansion / tiedoston luomista sen nimi (f$ = findfile() : if f$ <> "." and f$ <>".." then newFile()...)

Toisekseen, sinulla on aliohjelma joka poistaa tiedot kokoelmasta FILES, ja luo sinne uudet, mutta silti sinulla on ylimääräistä koodia heti alussa tiedostojen etsintään. Turhaa kirjoitustyötä, mikset vain kutsu aliohjelmaa Refresh_list heti alussa?

Kolmannekseen, sinulla on silmukka: Repeat ... Until i = 0. Tyylikkäämpää olisi kirjoittaa Repeat ... Until File\Name$ = ""

Edit. tai oikeastaan Repeat ... Until f$ = "", koska edellinen versio luo yhden tyhjän, turhan kansion.
-Vuoden 2008 aloittelijan ystävä -palkinnon voittaja-
Image <- protestipelikilpailun voittaja.
Space War

MrMonday
Advanced Member
Posts: 378
Joined: Fri Oct 10, 2008 2:35 pm

Re: Tilekartta editori Coolbasicilla

Post by MrMonday » Tue Sep 04, 2012 6:55 am

Huomenta, koneeni syövereistä hyppäsi joku vanha koodinpätkä ja hieman grafiikkaa, niin ajattelin nyt täällä sitten julkaista :)
Tilemap editor.zip
Tilekartta editori
(105.22 KiB) Downloaded 130 times
Eli kyseessä on siis työstämäni tilekartta editori, mikä jäi joskus kesken, eikä meikäläisellä oikein jaksa mielenkiinto riittää enää. Mutta jos tahdot, niin saa työstää loppuun, osaavissa käsissä perus toimiva systeemi on nopea kasata. Koodi on jäänyt kommentoimatta, että hieman saattaa hankaloittaa lukemista, niin voin katsoa, jos jossain vaiheessa saisin kommentit vielä sekaan.

MrMonday
Advanced Member
Posts: 378
Joined: Fri Oct 10, 2008 2:35 pm

Re: Tilekartta editori Coolbasicilla

Post by MrMonday » Fri Dec 28, 2012 12:02 pm

Jälleen kerran sain inspiraation lähteä säätämän tämän tuomiopäivän projektin kanssa, mutta tällä kertaa muutoksista suurimpana mainittakoon, että taulukot vaihtui tyyppeihin, koska tyypit vaan toimivat itselläni paremmin :) Yö meni kätevästi koodaillessa, mutta jotain pientä tuli valmiiksikin:

Code: Select all

SCREEN 320,320

Type MAP        // Luodaan kokoelma karttaa varten.
    Field x     // Tilen x-sijainti.
    Field y     // Tilen y-sijainti.
    Field x2    // Poiminnan x-sijainti.
    Field y2    // Poiminnan y-sijainti.
    Field img   // Tilen kuva.
    Field dat   // Tilen data-arvo.
    Field lay   // Kartan kerros.
EndType

tileset_img = LoadImage("media/tileset.bmp") // Ladataan tilesetti.

_data  = 0 // Data-arvo.
layers = 3 // Kerrosten määrä

map_width   = 10 // Kartan leveys tileinä.
map_height  = 10 // Kartan korkeus tileinä.

tile_width  = 32 // Tilen leveys.
tile_height = 32 // Tilen korkeus.

tileset = tileset_img // Tässä ollut taas jotain todella jännää, en vaan muista mikä tämän idea oli.

// Tehdään pyyhekumia varten tyhjä kuva.
//(Tämän voisi varmasti tehdä fiksumminkin)

empty_tile  = MakeImage(tile_width,tile_height)

// Tehdään tileä varten kuva, johon poimittu tile kopioidaan
// ja josta se kopioidaan karttaan.

tile_img    = MakeImage(tile_width,tile_height)

// Luodaan kartta-kokoelmaan tyhjiä paikkoja...

For layer = 0 To layers-1 //...jokaiseen kerrokseen...
    For y = 0 To map_height-1 //...kartan korkeudelta...
        For x = 0 To map_width-1 //...ja leveydeltä.

        tile.MAP = New(MAP)
        
            tile\x   = x*tile_width
            tile\y   = y*tile_height
            tile\img = CloneImage(empty_tile)
            tile\dat = _data
            tile\lay = layer  
    
        Next x
    Next y
Next layer

layer = 0 // Asetetaan kerros takaisin nollaksi, muuten se jäisi for-silmukan jälkeen viimeiseksi.

//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////

// Tässä aliohjelmassa asetetaan tile karttaan.

Drop_tile:

    ClearMouse

Repeat

    // Asetetaan ikkunan ylälaitaan tietoja.

    SetWindow "Layer: "+layer+" Data: "+_data+" Tool: "+tool$

    // Tilen data-arvoa ja kartan kerrosta saa säädettyä nuolinäppäimistä. 

    If KeyHit(205) Then _data = _data + 1 
    If KeyHit(203) Then _data = _data - 1

    If KeyHit(200) Then layer = layer + 1
    If KeyHit(208) Then layer = layer - 1

    If layer < 0 Then layer = 0
    If layer > layers-1 Then layer = layers-1

    // Jos painetaan välilyöntiä, niin työkalu vaihtuu pyyhekumiksi.
    // Se palautuu automaattisesti kynäksi kun poimitaan tilesetistä uusi palikka.

    If KeyHit(57) Then tile_img = empty_tile : tool$ = "Eraser"

    // Jos hiiren vasen painike on pohjassa, niin tarkistetaan että hiiri on kartan rajojen sisäpuolella.
    // Sen jälkeen tallennetaan hiiren tile-sijainti muuttujiin

    If MouseDown(1)
        If MouseX() > 0 And MouseX() < map_width*tile_width And MouseY() > 0 And MouseY() < map_height*tile_height

            drop_x = (MouseX()/tile_width)*tile_width
            drop_y = (MouseY()/tile_height)*tile_height

            tile = First(MAP) // Siirrytään karttakokoelman ensimmäiseen jäseneen.
            
            Repeat // Aloitetaan silmukkaa...

                // Jos hiiren sijainti vastaa tilen sijaintia, niin muokataan tileä.
                
                If tile\x = drop_x And tile\y = drop_y And tile\lay = layer
    
                    tile\x2 = pick_x
                    tile\y2 = pick_y
                
                    tile\img = CloneImage(tile_img)
                    tile\dat = _data

                    Exit

                EndIf
                
                tile = After(tile)
         
            Until After(tile) = NULL //...mitä toistetaan kunnes tullaan viimeiseen jäseneen.
         
        EndIf
    EndIf        
        
    If MouseHit(2) Then Goto Pick_tile // Jos klikataan hiiren oikeaa painiketta, mennään tilenpoiminta-aliohjelmaan.

    If KeyHit(59) Then Gosub OpenMap // F1-näppäin lataa kartan.
    If KeyHit(60) Then Gosub SaveMap // F2-näppäin tallentaa kartan.
        
    Gosub DrawMap // Käydään piirtämässä kartta.

    // Piirretään laatikko kertomaan hiiren sijainti.
    Color 255,255,0
    Box (MouseX()/tile_width)*tile_width,(MouseY()/tile_height)*tile_height,tile_width,tile_height,0

    DrawScreen // Ehkä arvaatte...
    
Until KeyHit(1)

End

//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////

// Tässä aliohjelmassa poimitaan kuva tilesetistä.

Pick_tile:

    ClearMouse

Repeat

    DrawImage tileset,0,0 // Helpottaa työskentelyä kun piirretään tilesetti näkyviin.
    
    // Jos hiiren vasenta näppäintä klikataan, niin kopioidaan tilesetistä valitusta kohtaa kuva alussa luotuun kuvaan.
    If MouseHit(1)
    
        pick_x = (MouseX()/tile_width)*tile_width // Otetaan poiminnan x-sijainti talteen.
        pick_y = (MouseY()/tile_height)*tile_height // Otetaan poiminnan y-sijainti talteen.
        CopyBox pick_x,pick_y,tile_width,tile_height,0,0,Image(tileset),Image(tile_img)
        tool$ = "Pen" // Asetetaan työkaluksi kynä.
    
    EndIf
   
    If MouseHit(2) Then Goto Drop_tile // Jos klikataan hiiren oikeaa näppäintä, niin siirrytään asettamaan poimittua kuvaa karttaan.

    // Jälleen piirretään laatikko kertomaan hiiren sijainti.
    Box (MouseX()/tile_width)*tile_width,(MouseY()/tile_height)*tile_height,tile_width,tile_height,0

    DrawScreen

Until KeyHit(1)

End

//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////

DrawMap:
  
    tile = First(MAP)
            
    For l = 0 To layers-1
        For y = 0 To map_height-1
            For x = 0 To map_width-1
                    
            If After(tile) <> NULL
                DrawImage tile\img,tile\x,tile\y
                tile = After(tile)
            Else
                tile = First(MAP)
                Exit
            EndIf
            
            Next x
        Next y
    Next l

Return

OpenMap:

    map_file = OpenToRead("map.dat")
    
        For tile.MAP = Each MAP

                tile\x      = ReadInt(map_file)
                tile\y      = ReadInt(map_file)
                tile\x2     = ReadInt(map_file)
                tile\y2     = ReadInt(map_file)
                tile\dat    = ReadInt(map_file)
                tile\lay    = ReadInt(map_file)
                
                CopyBox tile\x2,tile\y2,tile_width,tile_height,0,0,Image(tileset),Image(tile\img)
                
        Next tile

    CloseFile map_file

Return

SaveMap:

    map_file = OpenToWrite("map.dat")
         
        For tile.MAP = Each MAP
    
                WriteInt map_file, tile\x
                WriteInt map_file, tile\y
                WriteInt map_file, tile\x2
                WriteInt map_file, tile\y2
                WriteInt map_file, tile\dat
                WriteInt map_file, tile\lay
                
        Next tile

    CloseFile map_file

Return
Nykyisellään lataus kusee vielä hieman, mutta varmaan siihen jotain keksin ja ryhdyn katselemaan ominaisuuksia sitten tarkemmin. Tällä hetkellä tässä hyvin alkeellisessa viritelmässä toimii loputtomat kerrokset, ja kätevästi myös maskiväri toimii, mikä taas mahdollistaa ehke hieman pienempiä tilesettejä. Datakerrosta ei ole erikseen ollenkaan, vaan data-arvo voidaan tallentaa jokaiseen tileen erikseen. Mutta tämä on tosiaan vielä ihan alkutekijöissään, joten tekemistä löytyy vielä paljon.
EDIT:

Huom. Tämä on sitten tosiaan hieman väsyneenä kirjotettu, eikä hirveästi suunniteltu, että optimoitavaa löytyy varmasti paljon, mutta keskityn siihen sitten kun saa muuten tätä projektia hieman enemmän eteenpäin :)

EDIT:

20 X 20 X 10 (4000 tileä, ihan kiitettävästi cb:ltä) ja fps pysyttelee nätisti siinä kymmenen tuntumassa :P Täytyy kokeilla CbE:llä, jos pyörisi hieman paremmin.


User avatar
MetalRain
Active Member
Posts: 188
Joined: Sun Mar 21, 2010 12:17 pm
Location: Espoo

Re: Tilekartta editori Coolbasicilla

Post by MetalRain » Fri Dec 28, 2012 8:07 pm

MrMonday wrote:
EDIT:

20 X 20 X 10 (4000 tileä, ihan kiitettävästi cb:ltä) ja fps pysyttelee nätisti siinä kymmenen tuntumassa :P Täytyy kokeilla CbE:llä, jos pyörisi hieman paremmin.

Saat hurjasti lisää suorituskykyä kun teet joka kerrokselle oman koko kartan laajuisen kuvan johon kopioit valitun tilen tai piirrät neliön maskivärillä kun haluat pyyhkiä. Nämä voidaan sitten piirtää kerrosnumeroiden mukaan järjestyksessä ja mahdollistaa jopa kerrosten erottamisen toisistaan käyttämällä pientä offsettiä kerrosten piirrossa windows 7:n ikkunamanagerin tyyliin (win + tab). Toinen varsin mukava hyöty on että voi käyttää marcoderin kuvanskalaaus funktiota ja zoomata koko karttaa varsin pienellä suorituskyvyn menetyksellä.

User avatar
Jonez
Devoted Member
Posts: 575
Joined: Mon Aug 27, 2007 8:37 pm

Re: Tilekartta editori Coolbasicilla

Post by Jonez » Sat Dec 29, 2012 12:30 pm

MetalRain wrote: Saat hurjasti lisää suorituskykyä kun teet joka kerrokselle oman koko kartan laajuisen kuvan johon kopioit valitun tilen tai piirrät neliön maskivärillä kun haluat pyyhkiä.
Ehdottomasti näin :). Aina huono puoli taitaa olla siinä, että cb:llä näytön resoluutiota (tms) suuremmat kuvat menevät pikselimössöksi reunoilta, ja se pitää kiertää useammalla kuvalla.
-Vuoden 2008 aloittelijan ystävä -palkinnon voittaja-
Image <- protestipelikilpailun voittaja.
Space War

User avatar
Misthema
Advanced Member
Posts: 312
Joined: Mon Aug 27, 2007 8:32 pm
Location: Turku, Finland
Contact:

Re: Tilekartta editori Coolbasicilla

Post by Misthema » Sat Dec 29, 2012 4:37 pm

Jonez wrote:
MetalRain wrote: Saat hurjasti lisää suorituskykyä kun teet joka kerrokselle oman koko kartan laajuisen kuvan johon kopioit valitun tilen tai piirrät neliön maskivärillä kun haluat pyyhkiä.
Ehdottomasti näin :). Aina huono puoli taitaa olla siinä, että cb:llä näytön resoluutiota (tms) suuremmat kuvat menevät pikselimössöksi reunoilta, ja se pitää kiertää useammalla kuvalla.
Kyllä, mutta luulenpa että kuvien mössääntymisen voi kiertää DrawImageBox:lla, mikäli ymmärsin oikein...
Vai oliko se ongelma siinä, kun yrität luoda/piirtää ruutua isompaan kuvaan? Itse en ole tainnut edes moiseen törmätä... o_o

User avatar
MetalRain
Active Member
Posts: 188
Joined: Sun Mar 21, 2010 12:17 pm
Location: Espoo

Re: Tilekartta editori Coolbasicilla

Post by MetalRain » Sat Dec 29, 2012 5:26 pm

Eilen koodailin tommosta esimerkkiä jossa kuvat copyboxataan pääkuvaan. Kuten Jonez mainitsi voi isot kuvat olla haasteellisia. Omalla koneella huomasin että makeimage ei toimi kuville joiden kokoluokka on noin 10000x10000px veikkaisin että jokin hieman pienempi kahden potenssi olisi aika turvallinen valinta, tyyliin 1024x1024 ja isot kuvat hajoitettaisiin pienempiin paloihin. Parhaimmillaan sain kolmelle kerrokselle varattua 300x350 32x32 tilekoolla varustetun kuvan eli kolme kappaletta 9600x11200 kuvia tämän jälkeen kokoa tai kerroksia kasvattamalla vain makeimage erroria pukkasi.

Tässä vielä esimerkkikoodi "kartasta" johon piirrellään joka frame 100 uutta tileä ja kerroksia on 15. Hiirellä voi liikuttaa kerroksia toisistaan eroon.

Code: Select all

SCREEN 1024,768

//muutama kirjaston vaatima globaali muuttuja
Dim ScreenImages(255) As integer 
Global ScreenEmptyImage, ScreenImageCount, ScreenImageLimit, ImageScreenInitialized
Global gScaledImage
gScaledImage = MakeImage(1, 1)

SAFEEXIT OFF 

// tästä voi säätää kokoa
Const LAYERS = 15
Const TILE_W = 32
Const TILE_H = 32

SW = ScreenWidth() / TILE_W - 2
SH = ScreenHeight() / TILE_H - 2

//alustetaan kuvakirjasto
InitializeImageScreenLibrary()

//luodaan kuvaruutu
map = MakeImageScreen(SW,SH,TILE_W,TILE_H,LAYERS)

img = MakeImage(TILE_W,TILE_H)
DrawToImage img
Color 0,0,0
Box 0,0,TILE_W,TILE_H
DrawToScreen 
//viedään kuva kuvataulukkoon
AddScreenImage(img)

//luodaan kuvat etukäteen
For i=0 To 100
    img = MakeImage(TILE_W,TILE_H)
    DrawToImage img
    Color Rnd(60,230),Rnd(60,230),Rnd(60,230)
    Box 0,0,TILE_W,TILE_H
    DrawToScreen 
    //viedään kuva kuvataulukkoon
    AddScreenImage(img)
Next i 

updateGoingOn = True 

Repeat

    If KeyHit(cbkeyreturn) Then updateGoingOn = Not updateGoingOn
    
    If (updateGoingOn) Then 

        // päivitetään joka frame karttaan 100 uutta tileä
        For i=0 To 100
            
            l = Rand(LAYERS)
            x = Rand(SW)
            y = Rand(SH)
            
            imageIndex = Rand(ScreenImageCount)
            
            If (Rand(5) > 0) Then imageIndex = 0
            
            ImageScreenPut(map,x,y,imageIndex,l)
        Next i
        
        ImageScreenUpdate(map)
    
    EndIf 

    mx# = MouseWX()*0.1
    my# = -MouseWY()*0.07
    
    ImageScreenDraw(map,TILE_W,TILE_H,mx#,my#)
    
    SetWindow "FPS: "+FPS()
    
    DrawScreen
    
Until EscapeKey()

//tyhjennetään muisti turhasta tauhkasta
DeleteImageScreen(map)
DeleteScreenImages()

End




Const BYTE_SIZE = 4

//offset of data in memoryblocks
Const MEMBLOCK_OFFSET_ScreenImageLayers = 0
Const MEMBLOCK_OFFSET_ScreenTextureWidth = 4
Const MEMBLOCK_OFFSET_ScreenTextureHeight = 8
Const MEMBLOCK_OFFSET_ScreenWidth = 12
Const MEMBLOCK_OFFSET_ScreenHeight = 16
Const MEMBLOCK_OFFSET_ScreenLayerAmount = 20
Const MEMBLOCK_OFFSET_ScreenBufferType = 24
Const MEMBLOCK_OFFSET_ScreenBuffer = 25
Const MEMBLOCK_OFFSET_ScreenRenderScaleFactor = 29
Const MEMBLOCK_SIZE_Screen = 33

Const MEMBLOCK_OFFSET_LayerBaseImage = 0
CONST MEMBLOCK_OFFSET_LayerScaledImage = 4
Const MEMBLOCK_OFFSET_LayerNewImageCount = 8
Const MEMBLOCK_OFFSET_LayerNewImageList = 12
Const MEMBLOCK_OFFSET_LayerNewImageListSize = 16
Const MEMBLOCK_SIZE_Layer = 20

Const MEMBLOCK_OFFSET_ImageIndex = 0
Const MEMBLOCK_OFFSET_ImageX = 4
Const MEMBLOCK_OFFSET_ImageY = 8
Const MEMBLOCK_SIZE_Image = 12

Const LIST_INCREASE_SIZE = 20

Const BUFFERTYPE_MEMBLOCK = 1
Const BUFFERTYPE_STREAMFILE = 2

Function InitializeImageScreenLibrary(limit=255)
    ScreenEmptyImage = MakeImage(10,10)
	ScreenImageLimit = limit
    ReDim ScreenImages(limit) As integer 
    ScreenImageCount = 0
    ImageScreenInitialized=1
End Function 

Function MakeImageScreen(width=16, height=16, imageW=32, imageH=32, layerAmount=10)
   
    mem = MakeMEMBlock(MEMBLOCK_SIZE_Screen)
    
    width = Max(width, 1)
    height = Max(height, 1)
    
    PokeInt mem,MEMBLOCK_OFFSET_ScreenTextureWidth, imageW
    PokeInt mem,MEMBLOCK_OFFSET_ScreenTextureHeight, imageH

    PokeInt mem,MEMBLOCK_OFFSET_ScreenWidth, width 
    PokeInt mem,MEMBLOCK_OFFSET_ScreenHeight, height
	
    PokeInt mem,MEMBLOCK_OFFSET_ScreenLayerAmount, layerAmount
	
	PokeFloat mem, MEMBLOCK_OFFSET_ScreenRenderScaleFactor, 1.0
	
	//use buffer only if it's small enough
	if (width * height * layerAmount < 100000) Then 
		PokeByte mem,MEMBLOCK_OFFSET_ScreenBufferType, BUFFERTYPE_MEMBLOCK
	else 
		PokeByte mem,MEMBLOCK_OFFSET_ScreenBufferType, BUFFERTYPE_STREAMFILE
	endif 
	
	ClearImageScreen(mem)
    
    Return mem
End Function 

//Deletes Image Screen
Function DeleteImageScreen(mem)
    
	if (mem and MEMBlockSize(mem) = MEMBLOCK_SIZE_Screen) Then 
	
		layerObjects = Peekint(mem,MEMBLOCK_OFFSET_ScreenImageLayers)
		
		layerAmount = PeekInt(mem,MEMBLOCK_OFFSET_ScreenLayerAmount)
		
		// delete previous layer images and memblocks if present
		
		if (layerObjects) then 
			
			for iterator=0 to MemBlocksize(layerObjects)-1 step BYTE_SIZE
			
				layer = PeekInt(layerObjects, iterator)
				
				if (layer) Then 
				
					layerImage = PeekInt(layer,MEMBLOCK_OFFSET_LayerBaseImage)
					
					if (layerImage) then DeleteImage layerImage
					
					changeList = PeekInt(layer,MEMBLOCK_OFFSET_LayerNewImageList)
					
					if (changeList) then 
						
						DeleteMEMBlock changeList
						
					endif 
					
					DeleteMEMBlock layer

				Endif 

			Next iterator
			
			DeleteMEMBlock layerObjects
			
		EndIf 
		
		bufferType = PeekByte(mem,MEMBLOCK_OFFSET_ScreenBufferType)
		
		if (bufferType = BUFFERTYPE_MEMBLOCK) then 
			screenBuffer = PeekInt(mem,MEMBLOCK_OFFSET_ScreenBuffer)
			// remove screen buffer
			if (screenBuffer) then DeleteMEMBlock screenBuffer
			
		endif 
		
		DeleteMEMBlock mem

    EndIf 
End Function 

//Clears all ImageScreen layerObjects
function ClearImageScreen(mem)

	If mem Then 
		If MEMBlockSize(mem) = MEMBLOCK_SIZE_Screen Then 
		
			width = PeekInt(mem,MEMBLOCK_OFFSET_ScreenWidth)
			height = PeekInt(mem,MEMBLOCK_OFFSET_ScreenHeight)
			layerAmount = PeekInt(mem,MEMBLOCK_OFFSET_ScreenLayerAmount)
			bufferType = PeekByte(mem,MEMBLOCK_OFFSET_ScreenBufferType)
			
			if (bufferType = BUFFERTYPE_MEMBLOCK) then 
				screenBuffer = PeekInt(mem,MEMBLOCK_OFFSET_ScreenBuffer)
				// remove screen buffer
				If (screenBuffer) then DeleteMEMBlock screenBuffer
				// init screen buffer
				PokeInt mem,MEMBLOCK_OFFSET_ScreenBuffer, MakeMEMBlock(width * height * layerAmount * BYTE_SIZE)
			endif 

			// init new memblocks and images for layerObjects
			ImageScreenInitLayers(mem) 
			
		endif 

	endif 

end function 

//(Re)creates ImageScreen layerObjects
Function ImageScreenInitLayers(mem) 

    If ImageScreenInitialized=0 Then MakeError "You must call ImageScreenInitialize() before calling other ImageScreen functions!"

	if (mem and MEMBlockSize(mem) = MEMBLOCK_SIZE_Screen) Then 
	
		previousLayers = Peekint(mem,MEMBLOCK_OFFSET_ScreenImageLayers)
		
		layerAmount = PeekInt(mem,MEMBLOCK_OFFSET_ScreenLayerAmount)
		
		// delete previous layer images and memblocks if present
		
		if (previousLayers) then 
			
			for iterator=0 to MemBlocksize(previousLayers)-1 step BYTE_SIZE
			
				layer = PeekInt(previousLayers, iterator)
				
				if (layer) Then 
				
					layerImage = PeekInt(layer,MEMBLOCK_OFFSET_LayerBaseImage)
					
					if (layerImage) then DeleteImage layerImage
					
					changeList = peekint(layer,MEMBLOCK_OFFSET_LayerNewImageList)
					
					if (changeList) Then 
						
						DeleteMEMBlock changeList
						
					endif 
					
					DeleteMEMBlock layer

				Endif 

			next iterator
			
			DeleteMEMBlock previousLayers
			
		EndIf 

		width = PeekInt(mem,MEMBLOCK_OFFSET_ScreenWidth)
		height = PeekInt(mem,MEMBLOCK_OFFSET_ScreenHeight)
		
		//create new layerObjects 
	
		layerObjects = MakeMemblock(BYTE_SIZE * layerAmount)
		
		textureWidth = PeekInt(mem,MEMBLOCK_OFFSET_ScreenTextureWidth)
		textureHeight = PeekInt(mem,MEMBLOCK_OFFSET_ScreenTextureHeight)
		
		for iterator=0 to layerAmount-1
		
			layer = MakeMemBlock(MEMBLOCK_SIZE_Layer)
			
			PokeInt layer, MEMBLOCK_OFFSET_LayerBaseImage, MakeImage(width * textureWidth, height * textureHeight)
			PokeInt layer, MEMBLOCK_OFFSET_LayerScaledImage, MakeImage(1,1) 
			PokeInt layer, MEMBLOCK_OFFSET_LayerNewImageCount, 0
			
			changeListSize = LIST_INCREASE_SIZE * MEMBLOCK_SIZE_Image
			
			PokeInt layer, MEMBLOCK_OFFSET_LayerNewImageListSize, changeListSize
			
			PokeInt layer, MEMBLOCK_OFFSET_LayerNewImageList, MakeMEMBlock(changeListSize)

			PokeInt layerObjects, iterator * BYTE_SIZE, layer
			
		next iterator
		
		PokeInt mem, MEMBLOCK_OFFSET_ScreenImageLayers, layerObjects 
	
	Endif 
	
End function 

//Sets value to ImageScreen
Function ImageScreenPut(mem, x, y, imageIndex=0, layer=0, fillLayer=0, fillAllLayers=0)

    If (mem And layer > -1 and imageIndex >= 0 and imageIndex < ScreenImageCount) Then 
        If MEMBlockSize(mem) = MEMBLOCK_SIZE_Screen Then 
		
            width = PeekInt(mem,MEMBLOCK_OFFSET_ScreenWidth)
            height = PeekInt(mem,MEMBLOCK_OFFSET_ScreenHeight)
            layerAmount = PeekInt(mem,MEMBLOCK_OFFSET_ScreenLayerAmount)
			layerObjects = PeekInt(mem,MEMBLOCK_OFFSET_ScreenImageLayers)
			bufferType = PeekByte(mem,MEMBLOCK_OFFSET_ScreenBufferType)
			
			if (bufferType = BUFFERTYPE_MEMBLOCK) then screenBuffer = PeekInt(mem,MEMBLOCK_OFFSET_ScreenBuffer)
			
			//put value to only one cell
            If (fillLayer=0 And layerObjects <> 0 ) Then 
			
				//check that coordinates are inside of screen and layer exists 
                If ( x => 0)( x < width )( y => 0)( y < height )( layer < layerAmount) Then 
				
					//start at last layer if clearing all layerObjects 
					if (fillAllLayers=1) Then layerIndex = layerAmount-1 Else layerIndex = layer
					
					// loop through all layerObjects 
					while (layerIndex >= 0)
					
						// if buffer is used check old value 
						If (bufferType = BUFFERTYPE_MEMBLOCK) then 
							// get old value
							oldValue = PeekInt (screenBuffer,(x + y * width + layerIndex * width * height) * BYTE_SIZE)
							writeValue = (oldValue <> imageIndex )
						Else 
							writeValue = true
						EndIf 

	
						If (writeValue) then 
						
							//set buffer value to imageIndex
							if (bufferType = BUFFERTYPE_MEMBLOCK) then PokeInt screenBuffer,(x + y * width + layerIndex * width * height) * BYTE_SIZE, imageIndex
							
							layerObject = Peekint(layerObjects, layerIndex * BYTE_SIZE) 
							
							if (layerObject <> 0) Then 
							
								layerChangeList = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageList)
								
								if (layerChangeList <> 0) Then 
								
									layerChangedAmount = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageCount)
									
									changeListSize = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageListSize)
									
									//changelist is too small, increase size
									if ( changeListSize < (layerChangedAmount+1) * MEMBLOCK_SIZE_Image) then 
									
										newSize = (layerChangedAmount + LIST_INCREASE_SIZE) * MEMBLOCK_SIZE_Image
										ResizeMEMBlock layerChangeList, newSize
										
										//resize can alter pointer so save
										pokeint layerObject, MEMBLOCK_OFFSET_LayerNewImageList, layerChangeList
										
										
										//store new size 
										PokeInt layerObject, MEMBLOCK_OFFSET_LayerNewImageListSize, newSize
									
									
									endif 
									
									// Add value to changelist 
									PokeInt layerChangeList, layerChangedAmount * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageIndex, imageIndex
									PokeInt layerChangeList, layerChangedAmount * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageX, x
									PokeInt layerChangeList, layerChangedAmount * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageY, y
									
									//increase changelist counter 
									PokeInt layerObject, MEMBLOCK_OFFSET_LayerNewImageCount, layerChangedAmount + 1
									
								endif 
								
							Endif 
							
						EndIf 
						
						//break out if not going to clear all layerObjects
						if (fillAllLayers=0) Then exit
					
					wend 
                    
                EndIf 
				
			// fill this layer 
            ElseIf fillLayer=1 And fillAllLayers=0 Then 
			
				// layer exists 
                If (layer < layerAmount) Then 
				
					layerObject = Peekint(layerObjects, layer * BYTE_SIZE) 
						
					layerChangeList = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageList)
					layerChangedAmount = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageCount)
					changeListSize = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageListSize)
					
					//loop through layer 
                    For x=0 To width - 1
                        For y=0 To height - 1
						
							// if buffer is used check old value 
							if (bufferType = BUFFERTYPE_MEMBLOCK) then 
								// get old value
								oldValue = PeekInt (screenBuffer,(x + y * width + layer * width * height) * BYTE_SIZE)
								writeValue = (oldValue <> imageIndex )
							else 
								writeValue = true
							endif 

							if (writeValue) then 
							
								//set buffer value to imageIndex
								if (bufferType = BUFFERTYPE_MEMBLOCK) then PokeInt screenBuffer,(x + y * width + layer * width * height) * BYTE_SIZE, imageIndex
								
								//changelist is too small, increase size
								if ( changeListSize < (layerChangedAmount+1) * MEMBLOCK_SIZE_Image) then 
									newSize = (layerChangedAmount + LIST_INCREASE_SIZE) * MEMBLOCK_SIZE_Image
									ResizeMEMBlock layerChangeList, newSize
									
									//resize can alter pointer so save
									pokeint layerObject, MEMBLOCK_OFFSET_LayerNewImageList, layerChangeList
									
									//store new size 
									PokeInt layerObject, MEMBLOCK_OFFSET_LayerNewImageListSize, newSize
									
								endif 
								
								// Add value to changelist 
								PokeInt layerChangeList, layerChangedAmount * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageIndex, imageIndex
								PokeInt layerChangeList, layerChangedAmount * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageX, x
								PokeInt layerChangeList, layerChangedAmount * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageY, y
								
								//increase changelist counter 
								PokeInt layerObject, MEMBLOCK_OFFSET_LayerNewImageCount, layerChangedAmount + 1

                            EndIf 
							
                        Next y
                    Next x
					
                EndIf 
				
			// clear all -- this is expensive call, avoid if possible
            ElseIf fillLayer=1 And fillAllLayers=1 Then 
			
				 ClearImageScreen(mem)
				
            EndIf 
			
        EndIf 
    EndIf 
End Function 

//Applies ImageScreen Changes 
Function ImageScreenUpdate(mem)

    If mem Then 
        If MEMBlockSize(mem) = MEMBLOCK_SIZE_Screen Then 
		
			width = PeekInt(mem,MEMBLOCK_OFFSET_ScreenWidth)
			height = PeekInt(mem,MEMBLOCK_OFFSET_ScreenHeight)
			
			textureWidth = PeekInt(mem,MEMBLOCK_OFFSET_ScreenTextureWidth)
			textureHeight = PeekInt(mem,MEMBLOCK_OFFSET_ScreenTextureHeight)
			
			layerAmount = PeekInt(mem,MEMBLOCK_OFFSET_ScreenLayerAmount)
			layerObjects = PeekInt(mem, MEMBLOCK_OFFSET_ScreenImageLayers)
			
			scaleFactor# = PeekFloat(mem, MEMBLOCK_OFFSET_ScreenRenderScaleFactor)
			
			if ( layerObjects ) Then 
			
				for layerIndex = 0 to layerAmount-1
				
					layerObject = Peekint(layerObjects, layerIndex * BYTE_SIZE) 
					
					if (layerObject ) Then 
					
						layerImage = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerBaseImage)
						
						if layerImage then 
						
							layerChangeList = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageList)
							layerChangedAmount = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageCount)
							changeListSize = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerNewImageListSize)
							
							if (layerChangedAmount > 0 and layerChangeList <> 0) Then

								//apply changes to layer 
								for changeIterator = 0 to layerChangedAmount - 1

									value	=	PeekInt(layerChangeList, changeIterator * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageIndex)
									x		=	PeekInt(layerChangeList, changeIterator * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageX)
									y		=	PeekInt(layerChangeList, changeIterator * MEMBLOCK_SIZE_Image + MEMBLOCK_OFFSET_ImageY)
									
									If value >= 0 and value < ScreenImageCount Then 
										CopyBox 0,0,textureWidth,textureHeight,x*textureWidth,y*textureHeight,Image(ScreenImages(value)),Image(layerImage)
									Else
										Drawtoimage layerImage
											Color 0,0,0
											Box x*textureWidth,y*textureHeight,textureWidth,textureHeight
										DrawToScreen 
									EndIf 

								next changeIterator
								
								if (scaleFactor# <> 1.0) then 
								
									fLayerIndex# = -scaleFactor#^float( layerIndex)
									
									scaledImage = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerScaledImage)
									scaledImage = ScaleImage(layerImage, scaledImage, float(textureWidth*width)*fLayerIndex#, float(height*textureHeight)*fLayerIndex#)
									pokeint layerObject, MEMBLOCK_OFFSET_LayerScaledImage, scaledImage
									
								endif 
								
								suggestedSize = (layerChangedAmount * 2 ) * MEMBLOCK_SIZE_Image
								
								if (changeListSize > suggestedSize) then
								
									resizememblock layerChangeList, suggestedSize
									pokeint layerObject, MEMBLOCK_OFFSET_LayerNewImageList, layerChangeList
									pokeint layerObject, MEMBLOCK_OFFSET_LayerNewImageListSize, suggestedSize

								endif 

								//reset changed amount to zero 
								PokeInt layerObject, MEMBLOCK_OFFSET_LayerNewImageCount, 0
							
							Endif 
						
						EndIf
						
					EndIf 
					
				next layerIndex
				
			Endif 
             
        EndIf 
    EndIf 

End Function 

Function ImageScreenDraw(mem,imageScreenX#=0.0,imageScreenY#=0.0,layerOffsetX#=0.0, layerOffsetY#=0.0)

    If mem Then 
        If MEMBlockSize(mem) = MEMBLOCK_SIZE_Screen Then 
			
			layerAmount = PeekInt(mem,MEMBLOCK_OFFSET_ScreenLayerAmount)
			layerObjects = PeekInt(mem, MEMBLOCK_OFFSET_ScreenImageLayers)
			scaleFactor# = PeekFloat(mem,MEMBLOCK_OFFSET_ScreenRenderScaleFactor)
			
			width = PeekInt(mem,MEMBLOCK_OFFSET_ScreenWidth)
			height = PeekInt(mem,MEMBLOCK_OFFSET_ScreenHeight)
			
			textureWidth = PeekInt(mem,MEMBLOCK_OFFSET_ScreenTextureWidth)
			textureHeight = PeekInt(mem,MEMBLOCK_OFFSET_ScreenTextureHeight)

			for layerIndex = 0 to layerAmount-1
			
				layerObject = Peekint(layerObjects, layerIndex * BYTE_SIZE)
				layerImage = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerBaseImage)
				scaledImage = PeekInt(layerObject, MEMBLOCK_OFFSET_LayerScaledImage)

				if (scaleFactor# <> 1.0 ) then 
				
					fLayerIndex# = scaleFactor#^float(layerIndex)
				
					w# = float(textureWidth*width)
					widthDiff# = w#/2.0 - w#*fLayerIndex#/2.0
					
					h# = float(textureHeight*height)
					heightDiff# = h#/2.0 - h#*fLayerIndex#/2.0
				
					DrawImage scaledImage, imageScreenX+layerOffsetX#*float(layerIndex)+widthDiff#, imageScreenY+layerOffsetY#*float(layerIndex)+heightDiff#
				else 
				
					fLayerIndex# = float(layerIndex)
				
					DrawImage layerImage, imageScreenX+layerOffsetX#*fLayerIndex#, imageScreenY+layerOffsetY#*fLayerIndex#
				endif 
				
			next layerIndex

             
        EndIf 
    EndIf 

End Function 

//Adds image to Screen images and returns index of image
Function AddScreenImage(img) 

    If (img) Then 
        If (ScreenImageCount >= ScreenImageLimit) Then 
			ClearArray OFF
			ScreenImageLimit = ScreenImageLimit + LIST_INCREASE_SIZE 
			ReDim ScreenImages(ScreenImageLimit) As integer 
		EndIf
		
        ScreenImages(ScreenImageCount) = img
        ScreenImageCount = ScreenImageCount + 1
    Else 
        MakeError "Image is not valid to add into ImageScreen"
    
    EndIf 
	
	imgIndex = ScreenImageCount - 1
    
    Return imgIndex

End Function 

Function DeleteScreenImages()
    If ImageScreenInitialized=0 Then MakeError "You must call ImageScreenInitialize() before calling other ImageScreen functions!"

    For iterator = 0 To ScreenImageLimit
		If ScreenImages(ScreenImageLimit) Then DeleteImage ScreenImages(iterator)
    Next iterator

End Function


Function ScaleImage(_image, _scaled, _width, _height)
   //By: Marcoder
   //Modification: Little optimization handling with ImageWidth() And ImageHeight().
   
   If _width <= 0 Or _height <= 0 Then Return _scaled
   
   DeleteImage _scaled
   _scaled = MakeImage(_width, _height)
   
   _image_width = ImageWidth(_image)
   _image_height= ImageHeight(_image)
   
   // Tehdään temppikuva johon skaalataan ensin vain leveys
   lTempImage = MakeImage(_width, ImageHeight(_image))
   DrawToImage lTempImage
   For x = 0 To _width - 1
      sx# = Float(_image_width) / Float(_width) * Float(x)
      DrawImageBox _image, x, 0, sx, 0, 1, _image_height, OFF,OFF
   Next x
   lTempImage_width = ImageWidth(lTempImage)
   DrawToScreen
   
   // Skaalataan myös pystysuunnassa
   DrawToImage _scaled
   For y = 0 To _height - 1
      sy# = Float(_image_height) / Float(_height) * Float(y)
      DrawImageBox lTempImage, 0, y, 0, sy, lTempImage_width, 1, OFF,OFF
   Next y
   DrawToScreen
   DeleteImage lTempImage
   
   Return _scaled
End Function


User avatar
Latexi95
Guru
Posts: 1164
Joined: Sat Sep 20, 2008 5:10 pm
Location: Lempäälä

Re: Tilekartta editori Coolbasicilla

Post by Latexi95 » Sat Dec 29, 2012 9:16 pm

Kannattaisi vain laskea mitkä tilet ovat ruudulla ja piirtää ne. Homma olisi paljon helpompi kyllä jos tilet olisivat taulukossa, jolloin voisi helposti laskea raja-arvot ja for-loopilla vaan sitten käydä vain juuri ne tilet läpi. cbE:n tilekartan piirrosta voi ottaa mallia.

User avatar
Jonez
Devoted Member
Posts: 575
Joined: Mon Aug 27, 2007 8:37 pm

Re: Tilekartta editori Coolbasicilla

Post by Jonez » Thu Jan 03, 2013 2:07 pm

Latexi, olet myös ehdottomasti oikeassa (helppoa tää muiden komppaaminen), mutta jos tilejen koko on pieni suhteessa näytön kokoon, ei cb suoriudu tehtävästä millään. Paras tapa optimoida taitaa olla suurempaan kuvaan etukäteen piirtäminen.
-Vuoden 2008 aloittelijan ystävä -palkinnon voittaja-
Image <- protestipelikilpailun voittaja.
Space War

User avatar
Latexi95
Guru
Posts: 1164
Joined: Sat Sep 20, 2008 5:10 pm
Location: Lempäälä

Re: Tilekartta editori Coolbasicilla

Post by Latexi95 » Thu Jan 03, 2013 2:17 pm

Jos tilejen koko on hyvin pieni, niin minua ainakin epäilyttää kannattaako tilejä käyttää ollenkaan vai kannattaisiko käyttää ihan pelkkää kuvaa pelissäkin.

User avatar
Misthema
Advanced Member
Posts: 312
Joined: Mon Aug 27, 2007 8:32 pm
Location: Turku, Finland
Contact:

Re: Tilekartta editori Coolbasicilla

Post by Misthema » Mon Feb 04, 2013 2:36 pm

Hmmmmm.... Toisaalta taas mietin, että miksei tässä voida käyttää CB:n tilemappisysteemiä:

Code: Select all

SCREEN 800,600

'Create a map from Blank 
map=MakeMap(2048,2048,32,32)
u=LoadObject("Media\guy.bmp",72)

'Apply some graphics on it 
tileset=LoadImage("Media\tileset.bmp")
PaintObject map,tileset

'Randomly fill the map 
For y=1 To MapHeight()
For x=1 To MapWidth()
    If Rand(1,5)=5 Then 
        EditMap map,0,x,y,2 'drawing
        EditMap map,2,x,y,1 'collision
    Else 
        EditMap map,0,x,y,145
    EndIf
Next x
Next y

'The game loop-itself 
Repeat

    If UpKey() Then MoveObject u,8
    If DownKey() Then MoveObject u, -8
    If LeftKey() Then TurnObject u,5
    If RightKey() Then TurnObject u, -5
    
    'Glue camera to object position
    CloneCameraPosition u
    
    
    SetWindow ""+FPS()
    DrawScreen

Forever
Itsellä pyörii läppärillä 60fps paikkeilla kun koko ruutu on täynnä tilejä. CB:n tilemappisysteemi siis on melko pätevä ja näyttää hoitavan nämä teidän miettimät ongelmat jo sisäänrakennettuna. :P

Post Reply