GithubHelp home page GithubHelp logo

makipl / openviii-monogame Goto Github PK

View Code? Open in Web Editor NEW
620.0 42.0 60.0 78.39 MB

Open source Final Fantasy VIII engine implementation in C# working on Windows and Linux (Android and iOS planned too!) [Monogame]

License: MIT License

C# 98.14% Smalltalk 0.60% Roff 0.01% HLSL 0.23% Batchfile 0.01% HTML 0.98% Shell 0.04%
final fantasy viii final-fantasy-viii final-fantasy-8 8 game engine engine-reconstruction monogame

openviii-monogame's People

Contributors

albeoris avatar andrewdonoher avatar benjaminfoo avatar cmbasnett avatar deepsourcebot avatar flamehorizon avatar jwpritchard avatar minganmuon avatar noctarius avatar rjesustvd avatar sebanisu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openviii-monogame's Issues

FFmpeg Custom Class Ffcc has some memory leaks

If you cycle threw videos and watch memory usage in Visual Studio you can see the spikes going up when it loads something new. And it not come back down all the way. A new instance is created every time a new video is played. So the old one is leaving something behind.

Expand Save Support

For tracking progess on load/saving support.

  • Load saves from steam folder
  • gray out the continue selection if there are no saves.
  • choose the steam user id. Right now it chooses the first one.
  • emulator
  • non steam version
  • original pc release
  • decide what to do when there is no pre-existing save folder.
  • jump to most recent save after checking a slot.

Also right now can only Load games.

  • add saving support.
  • what format do we save in?

NewGame

  • Load init.out. - it's a partial save file with default state of things.

Optimize drawing of dialogs/menus

There menus get complex and with complexity comes slowdowns. It's really obvious on linux. And I can't just skip the draw call because some screens have animation. Like blinking arrows and such.

Though just getting the menus done first I think is important. We can go back over them with hacks to decrease draw calls and calculations.

Readme- linux

Linux readme is wrong about apt-get install mono. It should be mono-devel and mono-complete

Missing contribution guide

This repo is missing a "how to get started" kind of file or a new section in the main readme file.

How can ppl get this running to contribute code? What does one need to install to contribute?

It being in Mono/C#, can ppl dev under Linux?

init_debugger_audio: DirectMusic not natively supported

DirectX 6 DirectMusic not natively supported with Unix. What now?
EDIT: I talk about DirectMusic .DTS and .SGT files.
Currently I'm wrapping real DX6 component. Linux may probably require pre-converted OGG sounds.

EDIT:

  • Implement loops
  • Fix tempo *
  • Add curves support
  • Investigate WAVE effects
  • Implement custom NAudio library for in-memory song writing
  • Maintain final quality

*Pulse per note = tick per note; milliseconds = 60 000 / (BMP * PPQ). Now: 120 * 2000 ?

battleDat: Animation linear interpolation

this is an enhancement of battle .DAT monster file:
currently the animation is set to be valid through FPS and a timer:

                float fpsVariable = 1000.0f / 15f;
                frameperFPS += Memory.gameTime.ElapsedGameTime.Milliseconds;
                if (frameperFPS > fpsVariable)
                {
                    frameperFPS = 0.0f;
                for (int x = 0; x < frame.Length; x++)
                    frame[x]++;
                }

by increasing the FPS, we would be able to add Nth animation frame, that is Lerp of:
start: frame[n], last: frame[n+1], step: x
where x is the distance between first and next frame. Therefore:

  • 30FPS should add one frame with step of 0.5 between frame[n] and frame[n+1];
  • 60FPS should add four frames with step of 0.25 between frame[n] and frame[n+1];
  • 5FPS should render only n/3 frames and skip those between

and etc... dynamically calculating
I'm putting this one as a remainder.

Xna SoundEffectInstance.pause won't work

I was going to add pausing to movie player this morning. But I could not get the audio to pause. Maybe it's how I set stuff up. I could pause the video. But the audio would start gliching instead of stopping. I maybe able to make a function to calculate where in the byte[] the audio position is and restart playback from that.

BattlePolish: grab monsters from encounter

Currently the renderer is set to show only the constant specified monsters (three). Change that so the monsters are actually grabbed from encounter data; utilize monsterPos array from Memory.Encounter

In Game Menu progress

I am going to start tracking my progress here:

Animations

  • Blinking Cursor
  • Transitions

90% Main

  • Hide unavailable options
  • Gray out disabled options
  • Gray text if dead
  • Yellow Text on low hp characters
  • Light blue text if affected with negative status effects.

85% Junction

  • After GF junctions changed jump to Auto
  • Pools - Prevent Cursor going to greyed out lines.
  • Character swapping with L1 and L2
  • Purple status Icons in between HP and Commands.
  • Light blue text if affected with negative status effects.

25% Items

  • Use Screen Group
    • Populate Item pool.
      • Item Name
      • Icon
      • Qty
      • Grey out text and disable selection when no valid targets
  • Populate Target pool. I merged GF and Character pools
    • Character Name
    • HP symbol
    • HP Integer
    • GF pool shows on GF item types.
    • GF name
    • HP symbol
    • GF HP Integer
    • I think a Red Line to indicate when not max hp might be useful.
    • Add functionality to all items (healing heals, etc)
      • healing, revive, status items
    • Light blue text if affected with negative status effects.
  • Show Statues
    • Light blue text if affected with negative status effects.
    • Purple status Icons
  • Rearrange group
    • Show two item pools
    • items on left can be moved to spots on right
  • Sort just arranges items automatically seems to be in item ID order.
    • Battle arrange group
    • Battle shows two small version of Item pool with only battle items
  • update help box with descriptions
  • don't forget to use events to trigger things to change on mode and such.

1% Battle Menu.

  • Overlay battlemenu over battle module.
  • Export from junction menu the command menu
    • Make command menu able to be moved from its position
    • add cursor
  • Export battle item menu from Items menu.
    • Make battle item menu able to be moved to new position
      • Trigger target window to cast magic with
  • Export magic menu from junction menu.
    • Magic menu to be exported from junction what order i wonder.
      • Trigger target window to cast magic with
  • Target Window
  • Draw Magic Window
    • Trigger target window to draw magic from
      • Display list of spells or gfs
        • Display draw/cast
          • if cast display target window again. might need two copies.
  • Blue Magic Pool
    • Shows pool of unlocked blue magic
    • Trigger target window to cast magic with
  • Setup modes
    • Starting - maki doing this stuff.
      • Spawn enemies
      • Spawn Characters
      • Do Camera animation
    • Battle
      • ATB charing
      • ATB full
      • GF charging
    • Victory
      • Display victory message/over the battle
        -[ ] Fade out the battle while music plays
      • Play Music
      • Exp Screen
        • Display who didn't get xp
      • Item Screen
        • Display received items
        • Display warning if have 100 already
      • AP Screen
        • Show if gf's level up
        • Show if gf unlocked ability
    • Game over.
      • Display game over message/over the battle
        -[ ] Fade out the battle while music plays
      • Play music
      • Jump to game over field
      • Stop playing music when leave field
  • make easy to swap character
    • Maybe have a different instance of Battle Menu class for each party member.
    • And have a parent object in charge of tracking which character's menu is on the screen.
  • HP bars and character names

50% Save

Parts are coded because they are the same as load screen.

  • Enable the screen.
  • Make update methods
  • Are you sure? dialog box
  • Complete checkitems in #61

I may redo the save/load parts a bit as I had remade the main ingame menu screen into a class. I had originally copied and pasted the code from the save/load screen. But It was a mess. And it didn't scale well. And I was making a new set of the same variables for each screen. O.o So yeah the save/load and Splash screen and debug menus will probably be recoded with the new class.

Rework old menus to use new class.

  • Load
  • Save
  • Splash
  • Debug

Movie Audio Thread gets stuck in loop when exiting.

When I exit while a video is playing the game doesn't quit. I pushed pause on the debugger and it was in the thread. since audio isn't playing the number of samples never changes so the loop goes on forever. I think to fix I might need to move the thread to ffcc class. So on dispose it kills the thread. Or I need to just kill the thread when I quit the game.

I think dispose is the better method. Though I was surprised it didn't throw an exception. :P

I'll put a fix in before my next pull request.

battle stage: some texture elements should be animated

example of Ifrit's cave shows animated lava.

Question is - how? (from the file view, not implementation)
I checked the documentation for stage files and:

  • there's 4 bits of unkown data for each triangle and quad that the other half is used for CLUT
  • Settings data that gets used by camera but actually holds variables for geometry rendering too

Exception with avio_alloc_context_read_packet::Invoke

Managed Debugging Assistant 'CallbackOnCollectedDelegate' 
  Message=Managed Debugging Assistant 'CallbackOnCollectedDelegate' : 'A callback was made on a garbage collected delegate of type 'FFmpeg.AutoGen!FFmpeg.AutoGen.avio_alloc_context_read_packet::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.'

I am unsure why but after a sound is done playing I guess the delegate is being called by avio. It doesn't happen all the time. I have seen it twice today.

I added lock around the code in the fixed statement. This should prevent any dispose from being called before the code is done executing.

The system will not let me ffmpeg.avio_context_free(&Decoder._format->pb); It causes a CTD when ever I try.

I hope the lock helps. The error is so rare.

The only reason I am using avio_read_content. Is that it is the only way I found to read ADPCM sounds out of memory.

TEX isn't handling iconfl00.TEX-iconfl03.TEX with pallets>=1 correctly.

I am having trouble with TEX. When i try to receive the highres icon textures pallet>0.

I am pretty sure the issue is in TEX.GetTexture()

I fed it the icon.tex and my code worked. When I gave it iconfl00.tex-iconfl03.tex it returns a corrupt texture.

It's possible texture handler is doing something wrong but it seems to be working.

The working ones
iconpcs_0_0
iconpcs_1_0
iconpcs_2_0
iconpcs_3_0
All the rest of them come up like this.
iconpcs_4_1
There is an image here ^ it's just blank.

I'll keep debugging maybe have to ref Vincent Tim some more.

module_battle_debug: animation change system

there's currently no animation system (they are all playing at constant animation index=0).
Frame[n] holds current frames for every entity, we should implement an animation index change system with animation blending available (new feature)

EDIT: Fix frame[n] for monster and characters due to recent change in instance system

Battle stage: Parsing error with Edea platform (a0stg147)

BS_PARSER_PRE_OBJECTSECTION: Main geometry section has no 6 pointers at: 4340

Encounters example:
195; 136
Could be probably some stupid. It's not a major issue (I mean it is, but there are more critical things to fix that one non-working stage).

FF8String vs FF8.Encoding

Currently we have at the moment two classes that provide the text encoding/decoding. No need for redundancy. I'd go with FF8.Encoding as it supports different chartables, has encoding capabilities and already have support for tags.

battleDat: Weapons have messed up UV

looks like the UV formula is valid for monsters only; Both characters and their weapons have invalid UVs
Currently : U (0-128)/128; V (0-128)/128 (if V>128 -> (V-128)/128

where 128 is constant currently. Looks like it corresponds to TIM texture resolution.
Either characters use -1 coordinates (1 is up, 0 is down) or they need dynamic dividor based on TIM resolution; To reverse...

SoundEffect LOOPSTART support broken

Music will play and loop but it will not loop from marked loop point.
MonoGame issue 5186
MonoGame pull 6607
Looks like this user has an open pull request for a fix. I had trouble finding his code to test.
So if his change gets approved this issue should go away.

I might be able to do a correct loop in naudio for windows only. I was reading about it someone using a custom class to wrap around the wavestream or something like that.

What kind of licenses can we use in this project?

Some kinds of licenses make the product dirty.

For example, the GNU GPLv3 lets people do almost anything they want with your project, except to distribute closed source versions.

At the same time, there are ready-made solutions, the use of which code can simplify life.

Is there a limit to the kinds of licenses that we can use during development?

Support Tonberry Mods

I have some basic file structure support right now. For files that had filenames this works 80%. Some pallets aren't detected correctly. Because for tonberry the filename doesn't matter as long as the hash is right. At least I think so.

Some mods have to use the hashmap to find out what texture and pallet to replace. So we would need to port the hash code from tonberry to c#. It's in the GlobalContext.cpp.

  • Basic file structure support ((\w{2})\w\d+) => $1\$2\$2*.png or $1\$2\$2_13-28*.png
  • Port the hash algorithm. Tonberry hashes the texture that direct3d is drawing. The source code was released and it's in c++
  • Find out what state the textures need to be in. We need a texture in a correct state to generate the same hash. We have the texture in it's raw 8/16 bit state and the converted to 24/32 bit state.
    I'm guessing it's the latter.
  • Be able to parse the csv files. These contain the modder's chosen filename and hash in decimal form.

Maybe it would be better to use a standard hash. Since they seem to want a new hash. Once we have mapped out all the textures we can run multiple hashes on all of them. Track the time and collision rate. Then we could suggest that be added to tonberry enhanced. Though tonberry doesn't check the entire texture so we could come up with tests like every other pixel and keep going till we get maximum speed and 0 collisions. https://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed

I am gonna put this on the back burner for now I wanted to put this here as a remember to come back to this.

AForge CTD

vfr = new VideoFileReader();
I decided to check to make sure everything was working on linux still before I kept going. When I selected the movie player on the debug menu it just exited. So I debugged line by line till I got to this line.

Question about Aforge on linux

Lag can cause Audio to get behind Video

If there is lag that causes the sound to skip it will desync. The video will end up ahead of the sound. This mostly only happens to me on linux in my vm. But I imagine someone with a weaker pc might have this issue on windows.
It basically needs to keep the Dynamic Sound Interface fed with audio samples. I was trying to increase the buffer size sent to it. But if I sent something other than 32 samples (approx 128 bytes) it caused sound glitches. I'm unsure if there is a way to detect if my audio is behind.
Possible Solutions:
Just increase the amount pre buffered?
FFMPEG audio processing in it's own thread?
Something faster than Mashal.Copy to copy from the byte* to byte[];? //when I switched to using Marshal.Copy to copy to a byte[] then feed it to Dynamic Sound Interface it was noticeably slower. But when I filled a memorystream with the entire uncompressed audio it would eat a lot of ram and that ram wouldn't always release correctly. Maybe there is a middleground.

TEX.TextureData.NumOfPalettes == 0 for Face_b00.TEX,Face_b01.TEX,Gf_big00.TEX,Gf_big01.TEX

TEX.TextureData.NumOfPalettes == 0 for Face_b00.TEX,Face_b01.TEX,Gf_big00.TEX,Gf_big01.TEX
So when I try to TEX.GetTexture(0) exception is thrown for null texture. If I set pallet = -1 it displays garbage.

The LoadPNG() works. I renamed the folder with the png textures to test the built in textures.
The UseBest() basically sees if pngTex==null use the built in texture.

Contents of TextureData:

  | Name | Value | Type
-------------------------
  | Height | 256 | uint
  | NumOfPalettes | 0 | byte
  | PaletteFlag | 0 | byte
  | PaletteSize | 0 | uint
  | Width | 256 | uint
  | paletteData | null | byte[]

Code from Init in my TextureHandler class I'm writing it to handle textures broken into chunks to support higher res.

ArchiveWorker aw = new ArchiveWorker(Memory.Archives.A_MENU);
                    string path = aw.GetListOfFiles().First(x => (x.IndexOf(string.Format(Filename, c + r * Cols + StartOffset), StringComparison.OrdinalIgnoreCase) >= 0));
                    tex = new TEX(ArchiveWorker.GetBinaryFile(Memory.Archives.A_MENU, path));
                    Texture2D pngTex = LoadPNG(path);

                    Textures[c, r] = (UseBest(tex, pngTex, out Vector2 scale));
                    Scales[c, r] = scale;

Code from UseBest()

    public static Texture2D UseBest(TEX _old, Texture2D _new, out Vector2 scale, int pallet = 0)
      {
          if (_new == null)
          {
              scale = Vector2.One;
              if (_old.TextureData.NumOfPalettes == 0)
                  return _old.GetTexture();
              return _old.GetTexture(pallet);
          }
          else
          {
              scale = GetScale(_old, _new);
              return _new;
          }
      }

Recompiling JSM scripts

I started writing support for JSM codes. I do it in a separate assembly, without changing the existing code. Currently ported Deling code to C#. I dunno how much is enough for me, but I hope to finish AST and nice formatting.

  • Investigation of Opcodes
    ⬛⬛⬛⬛⬛⬛⬜⬜⬜⬜ 60%
    We have an article on the wiki, a ready-made Deling and Garden sources, topics on the Qhimm forum and reverse engineering. Half the opcodes aren't documented.

  • Disassembling of instructions
    ⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 100%
    Handling the stack leads to a lot of errors. It is necessary to go from opcodes to a sequence of high-level instructions.
    PSHN_L(0); PSHN_L(127); MUSICVOL => SetMusicVolume(channel: 0, volume: 127)
    There was a lot of work done in Deling. Unfortunately, only basic instructions are described. The rest will have to finish. Currently, the stack sizes have been clarified for all instructions that were in valid files (several files don't correspond to the JSM standard or contain obvious errors [invalid jumps in test files], they will have to be processed separately).

  • Building of abstract syntax tree
    ⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ 100%
    The bulk of the work has already been done in Deling. It is necessary to eliminate crutches that hide bugs and remove spaghetti from the code.

  • Print decompiled sources
    ⬛⬛⬛⬛⬛⬛⬛⬛⬜⬜ 80%
    Similar to the previous paragraph. Bugs less, spaghetti more. Need to refactor code.
    Instead of pseudocode, it is better to use C# syntax.

if var622_ubyte == 128 begin
	if var599_ubyte == 32 begin
		var1041_ubyte = 1
	end
else if var622_ubyte < 128 begin
	if var622_ubyte > 1 begin
		var622_ubyte = 2
	else if var622_ubyte == 1 begin
		var622_ubyte = 1
	else if var617_ubyte > 1 begin
		var622_ubyte = 2
	else if var617_ubyte == 1 begin
		var622_ubyte = 1
	else if var618_ubyte > 1 begin
		var622_ubyte = 2
	else if var618_ubyte == 1 begin
		var622_ubyte = 1
	else if var620_ubyte > 1 begin
		var622_ubyte = 2
	else if var620_ubyte == 1 begin
		var622_ubyte = 1
	else if var621_ubyte > 1 begin
		var622_ubyte = 2
	else if var621_ubyte == 1 begin
		var622_ubyte = 1
	else if var616_ubyte > 1 begin
		var622_ubyte = 2
	else if var616_ubyte == 1 begin
		var622_ubyte = 1
	else
		var599_ubyte = 32
	end
end
ret(8)
  • Translate to expression tree / IL Code / Custom execution logic
    ⬛⬛⬛⬛⬛⬛⬛⬜⬜⬜ 60%
    The easiest way to execute code without creating your own state machine is to translate instructions into IL code or Expressions. But to support such a thing is difficult. If we choose this path, it is necessary to cover each expression with tests.
    But we can use Roslyn, after generating a C# code, and then parsing it.

  • Parsing of scripts
    ⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜ 0%
    To support modifications, it is necessary to learn how to parse the text representation of scripts, which is easy for players to edit. If we can use .NET Core and Roslyn, the easiest way is to write scripts in C# and parse them as Syntax Tree.

  • Testing
    ⬛⬛⬛⬛⬜⬜⬜⬜⬜⬜ 40%
    The current version enumerates all fileds and generates pseudo-code for them. There is one known bug that I am going to fix soon. In the future, it is necessary to cover with tests all the mechanisms for working with JSM, in order to eliminate bugs in this segment. Analyzing errors in it is VERY difficult.

CD 2000 version doesn't have lang-en folder

http://forums.qhimm.com/index.php?topic=18656.msg263759#msg263759

CD 2000 version doesn't have lang-en folder. I guess all the files are in data that would be in that folder. Requested him to post a tree /f of his ff8 directory. I think we might need to change our main directory from to data or the ff8 main directory. Then we just check if lang-en exists.

Labeled as enhancement as it's adding support for another version of the game not really fixing a bug.

init_debugger_audio: SoundID 28 not playing

ADPCM + stereo + normal sample rate
Totally no idea why it's not playing. It's the only sound that is not playing at all.

Current workaround is to force PCM decoding on this chunk, but it will produce glitches

Cache Strings

I was unsure if this should be automatic. Currently the Strings class only stores where the strings are. It does not save the strings. It assumes what ever screen requires the strings is saving those to a variable.
But there are times like in Load Game screen where I don't save the string. I read it every time we draw. And with locations that is loading from MAIN and MENU for each fontrender call using these strings.

I was thinking I could have the Strings class save the string to a dictionary before giving it to the caller. Then it can check to see if it already has it for future calls.
Or we could just change the class to load every string at startup into ram.

battleDat: Entities doesn't utilize bone0.pos

Every entity rendered is not transforming vertices by position. This can cause behaviour, where enemy such as bat will fly in-place
Currently we don't seem to know correct formula for calculating PositionTypes. Some sources claim x*.015f, some x*15f- none of them proved to be ultimately valid

FFmpeg.AutoGen 4.1.0.2 dll not found for kernel32 on linux

This is the lib i'm using to interface C# to ffmpeg. It was the best I could find.

Maybe this is because it's working with the windows dlls. I just ran my code and it's throwing a dll not found for kernel32. For this line _format = ffmpeg.avformat_alloc_context(); I think it's the lib I got from NuGet FFmpeg.AutoGen 4.1.0.2 per their github it will work in linux. If I understand it, we need to compile it ourselves with exact locations of the ffmpeg libraries.

module_battle_debug: Shadows

Entities lack shadow casting
Anyone have some idea of implementing a system for shadows? All I can think about at the moment is casual masked texture attached to the floor of bounding box

BattlePolish: Scale is wrong

Monsters (and characters+weapons [probably]) scale is not parsed properly/not used. Therefore a bug may be bigger than trex and even whole final form of ultimecia (last ultimecia form actually forms the stage)

Choose an open source license

Right now the project doesn't have a license.

When you make a creative work (which includes code), the work is under exclusive copyright by default. Unless you include a license that specifies otherwise, nobody else can copy, distribute, or modify your work without being at risk of take-downs, shake-downs, or litigation. Once the work has other contributors (each a copyright holder), “nobody” starts including you.

If you find software that doesn’t have a license, that generally means you have no permission from the creators of the software to use, modify, or share the software. Although a code host such as GitHub may allow you to view and fork the code, this does not imply that you are permitted to use, modify, or share the software for any purpose.

I propose to choose one of the most open licenses, if it doesn't contradict the original plan.

The MIT License is short and to the point. It lets people do almost anything they want with the project.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.