Techniques And Strategies For Data-driven Design In Game Development

1y ago
3 Views
2 Downloads
2.45 MB
117 Pages
Last View : 1m ago
Last Download : 3m ago
Upload by : Shaun Edmunds
Transcription

Techniques and Strategiesfor Data-driven design inGame DevelopmentScott ShumakerOutrage Games

MotivationsMany games are never completedMany completed games are notfinancially successfulThese failures are frequentlycaused by flaws in the developmentprocess

Game development is hardFrom a technology standpoint, gamedevelopment is no more difficult than othersoftware developmentHowever, properly functioning technology isjust one of many requirements for asuccessful titleThe majority of the development time is notspent developing technology, but content andgameplay

ContentArtLevelsMusicSound FXScriptingCutscenesBasically anything that isn’t code

GameplayRulesGoalsControlsAI and object behaviorOverall play mechanics

Fun and AppealMaking a game fun and appealing is one ofthe hardest challenges in game developmentDifficult to predict how a decision will impactfun factor until after it is actually implementedGameplay and content both require a largeamount of tweaking before the game looks,feels, and plays right

Fun and Appeal - SummaryFun and appeal are huge factors in agame’s commercial successThe difficulty in achieving and assessingthese important traits make them thebiggest risk in the projectImproving our process for adjustinggameplay and tweaking content willhelp us minimize risk

Case Study: PacMan

What makes PacMan fun?Level designzzzLocation of wallsLocation of dotsLocation of power-pillsEnemy behaviorzzzSpeed (before and after power pills)Respawn rateAIPlayer behaviorzzSpeedInvincibility time

Tweaking enemy andplayer speed, 1st attemptPac-man was designed a long time agoThey probably hard-coded the speed

Problems with 1stapproachPlayer and enemy have the samespeed, so you need to change it inmultiple places to tweak itWe need to recompile and re-run thegame to see the results of our changeOnly someone familiar with this specificcode can tweak it

Tweaking speed, 2nd approachPull the variables out and place them in a separate fileYou can do this with a #defineOr even better, with a const global variable

Problems withapproachnd2We still need to recompile and re-run tosee our changesYou still can’t expect a designer to beable to make changesDifferent, interrelated variables may stillbe spread across the code

Tweaking variablesPut all of the variables in a text file, exceltable or database to keep track of themDesigners or programmers can both edit this‘data source’Now, we could manually update the variablesin the code whenever they change in the datasourceInstead, why not enable our program to readin the data source itself?

Advantages of movingdata externallyWe no longer need to recompile to tweakvariablesDesigners and programmers can edit thedata sourceYou can view all of the variables at onceYou can even change these variables on aper-level basisYou can write more intuitive tools to edit thevariables

Extending the data sourceIn PacMan, you can apply this technique to morethan just numerical variablesLevels can be stored as some kind of data fileYou can write a level editor that will allow graphicalediting and then write out to this data formatThe game can then read in the data fileYou can extend this technique to virtually anyaspect of gameplay or contentzzzzzCharacter art (models / sprites)Visual effectsSpawning of enemies / powerupsAttacks, damage, healthEtc.

Case study SummaryCode is a poor location for behavior thatneeds to be changed frequentlyMoving game behavior out of code andinto data results in a more efficient processfor tweaking content and gameplayWe call this technique Data-Driven DesignThis lecture will discuss techniques toachieve good data-driven design

Part II - Data-drivendesign methodologies

Technique I:Separate Hard and SoftArchitecture

Hard ArchitectureHard Architecture is code that is low-level andwould be pretty uniform across different titlesExamples:zzzzzzRenderer (graphics system)Sound systemLow-level inputResource loader (I/O)Low-level utility classesMath library

Soft architectureSoft Architecture is code that is specificto the game that you are working onExamples:Powerup spawningz Inventory systemz Combat systemz Scoring systemz

Hard and Soft ArchitectureThe distinction is very importantSoft architecture is allowed to know about thehard architecture systems, but not vice versaOnly be your soft architectural systems thatare responsible for retrieving andmanipulating game dataAt some point, they might pass data to thehard architecture low-level systems

Technique II: Separatefunctionality intoSystems

TokensEvery discrete element of the game is a tokenExample: Pac-manzzzzzzDotsPower pillsGhostsPac-manThe ghost respawnerThe level itselfAll of these are tokens, or game elements

The systems approachWhat is a game system?A self-contained moduleOperates on some aspect of your gametokensUsually performs a piece of gamefunctionality and implement a specific type ofgame behaviorShould be able to be tested in isolation frommost other systems

Case Study: Smash TV 3DThe final 494 project that I and twoother programmers worked onDesigned as a modern, 3d version ofthe classic SNES and arcade gameSmash TVVery fast-paced action game filled withhordes of enemies, weapons, andpowerups

Case Study: Smash TV 3DGoals of enemy spawning systemFrenetic actionz Responsive to playerz Not too difficult, not too easyz Adjustable based on player difficultyz Good complement of enemiesz

Smash TV 3D Spawn SystemSpawn points – placed at various pointsin the level (usually behind the doors)Each spawn point is associated with anumber of wavesEach wave is a group of enemies(number, configuration, and delaybetween each enemy)

Spawn System 2

Spawn System AnalysisBehavior of the spawning system is verygame specificThe spawning system operates onspawn points, waves, and enemiesIt has sole responsibility for managingwaves and spawn points in the game,but for enemies, it only manages theircreation

The Systems ApproachGame systems manage the tokens in yourgame worldDesign your systems around functionalaspects of your game, not around the tokensthemselvesYou want each system to be responsible for aspecific game behavior, and you’ll find thatyour tokens end up interacting with multiplegame systems

Bad example #1Grunt systemIdea: A system that manages all aspects of the“grunt” enemies, including creation,initialization, behavior / AI, collisions,projectiles, death, rendering.Why it sucks:A large portion of the functionality in your gruntsystem will need to be duplicated for all yourother enemies, which will also requiresystems under this design

Bad Example #2Enemy SystemIdea: A system that manages all aspectsof all enemiesWhy it bites:You soon discover that the player alsoshares a lot of common functionalitywith enemies, like rendering, weapons,collision detection, etc.

Systems Approach StrategiesBreak up your systems by functionalityIn the previous examples, we might haveseparate systems for:zzzCreationWeaponsBehavior / AIA good rule of thumb: If there are sometokens in the world that could benefit fromsome of a system’s functionality, but theycannot use it because of other functionality inthe system, it should be split

Systems Approach SummaryFunctionality common to different objects isall in one place.Each system needs only limited knowledgeabout various tokens. This reduces coupling.If the system works with one kind of object, itwill work with all kinds of objects that have thesame aspect (this makes it easier to test)You can view each token as a set ofparameters to one or more systems. Thisallows you to tweak the tokens themselves tochange the way your game works.

Technique III:Component-basedArchitecture

Token ArchitectureMost games have many different typesof tokensMany tokens share some properties butdiffer in othersExample: Two different enemieszzzzBoth have ‘health’Both have ‘score’Probably have different AIMay have different movement types (e.g. flying or walking)

Token ArchitectureWe want to practice code and interfacere-use for tokensCopy and paste code hurts maintainabilityz Identical functionality in different tokensshould be treated uniformly by the systemthat manages that functionalityzHow do we structure our tokens to bestrealize code and interface re-use?

Approach I: Inheritancebased class hierarchyWe can use C inheritance to sharefunctionality andinterfaceThe inheritancediagram looks like this:

Bullet Bill:Enemyz Flyingz Non-animatingz

Inheritance hierarchySummaryThe class-based hierarchy approachhas serious problems with scaleVery complexNot robustPoor extendibility

Component-basedarchitectureInstead of inheritance, we usecontainment.Take each level of the class hierarchy,and change it to a component.This technique is called “Levelizing”.

Levelizing, ingBehaviorzzzEnemyPlayerPowerup

If we apply this approach, we end up with thefollowing for CGameObject:

Implementing thecomponentsThere are several methods for converting alevel of the hierarchy over into a componentThe first method involves using C inheritance – make a base class that eachclass on that level can inherit fromThe second method involves containment –you put all of the functionality in the basecomponent class

Inheritance Implementation

Containment Implementation

Implementation details, 4Sometimes you’ll actually end up with a classinheritance hierarchy off one of the components

Implementation Details, 5Class hierarchies aren’t completely evilThey just have serious scale problemsFor very simple hierarchies, they workfineGood rule of thumb: Don’t have ahierarchy with more than 3 levelsIf the hierarchy needs to get deeper,you should levelize it

Advantages of componentbased architecturesProvides code and interface re-usewithout scalability problemsWorks well with the systems approachPhysics system – movementz Rendering system – modelzComposition of objects isn’t fixed atcompile time – can change while thegame is running.

Token ArchitectureSummaryCode and interface re-use are highly desirablefor game object functionalityInheritance-based class hierarchies should onlybe used on limited numbers of object typesUse a component-based architecture foranything significantComponent-based architectures usecontainment rather than inheritanceComponent-based architectures also give runtime flexibility

Technique 4:Prototype-instance approach

Token CompositionIn a inheritance-based token hierarchy, thecomposition of each token is determined atcompile time by the inheritance tree

Token composition, 2In the component token architecture, everytoken is composed out of a number ofdifferent components and sub-componentsThe composition of a token is not defined atrun time.

Prototype definitionEach kind of token in your game has a‘prototype’ that describes the basic traitsof the tokenExample - Smash TV 3D enemies:Gruntsz Orbsz Mr. Shrapnelz Tanksz

PrototypesPrototypes specify the components that compose atokenThey can also specify the values of some of thevariables in those componentsPrototypes are shared among tokens of the sametypeExample: Each different enemy type has a uniquebehavior, appearance, score, etc.This information is the same for all instances of thatenemy typeAll of this shared information makes up the prototype

InstancesSome information is instance specific - itcan vary even among tokens of thesame typeExamples:Location in the levelz Velocityz Current hit pointsz Animation statez

Protoypes and instancesWhen an token is created, we want it to beinitialized with the properties in its prototypeWe only need to store one set of data foreach prototypeSome data we want to store for everyinstance of the token that currently exists inthe game world. This is called ‘instancespecific data’.

Prototype data – Wheredoes it come from?In Smash TV 3D, we had various types ofweapon projectiles in our games:zzzRocketsGrenades3-way spread shotEach of these projectiles had correspondingprototype dataThe weapons were created through a factoryfunction

Case study, part deuxA common approach is to initialize atoken’s prototype data in the creationroutines for the tokenYou probably want to have a listing ofall of the weapons side by side, tocompare their propertiesIn Smash TV 3D, we had a bunch ofenums and #defines at the top of a file

Weapons example

Case Study, continuedWhenever a weapon was constructed, thefactory would initialize it’s variables.p Weapon- SetDamage(kRocketWeaponDamage);p Weapon- SetSpeed(kRocketWeaponSpeed);This approach has many of the problems wediscussed in the Pac-man case study.The variables are all in code, which is a badplace for variables that change frequentlyDuring development, a good deal of time waswasted tweaking variables and thenrecompiling

ImprovementsWe want to move this information intoa text file or database (the “datasource”)This would allow us to just modify thedata source to test your changesHow do we associate the informationin the data source with the game?

Prototype IDsA prototype ID corresponds to an entry in our datasource that contains information for a specific prototypePrototype ID0123NameDamage Speed Amount Delay ModelNormal Shot11042 200 Normal.modelRocket2542 200 Rocket.modelSpreadShot11042 250 3WaySpreadShot.modelGrenades158450 Grenades.modelThis ID should be globally unique

Advantages of PrototypeIDsWe can avoid storing any of the prototype data in theclass at all. Instead of:m damage kRocketWeaponDamageWe get:CWeapon::GetDamage(){return GetWeaponDamage(m prototype id);}Where m protoype id would be initialized toPROTOTYPE ROCKET.

Prototype summaryAll of the information for your prototypesshould be stored externally in a data sourceThe game should read in the data source atrun-time and keep a database of prototypesin memory, each entry storing all of theinformation for a specific prototypeEach instance of a token should have aprototype ID so they can reference theirprototype when it is needed

The Mr. PotatoheadPrototype

Mix N’ MatchYou don’t need to have a different prototypefor every token that describes ALL of thetoken’s properties explicitlyNameModel Type Model Name Movement Mode Movement Speed Movement Turn Rate A I type A I A ggressiveness A I Morale A I LearningGruntA NIMA TING Grunt.model Walking5360 ENEMY0.510 NoInstead, you can have prototypescorresponding to each component in thetokenThen a prototype for a token will actually becomposed of sub-prototypes

Mix n’ Match, continuedIn Smash TV 3D, we could makeprototypes for the following nvincibility.modelModel TypeAnimatingAnimatingStaticPhysics type (movement mode)Prototype ID012zPrototype ID012Movement modeGroundAirAirSpeedTurn Rate536031801030AIPrototype ID AggressivenessMorale00.510.7Learning10 Yes8 No

More Mix n’ MatchYou could then have a prototype for anenemy look as follows:Grunt Prototype:zzzModel: Prototype 0 (Grunt.model)Physics: Prototype 0 (Walking)AI: Prototype 1The Grunt token is then composed of severalsub-prototypes, each which describes one ofthe grunt’s components (model, physics, AI)This allows different tokens to share subprototypes

Extending Mix n’ matchPrototypes can also reference other prototypesExample: The grunt prototype could reference aspecific weapon prototype, indicating the weaponthe grunt will use – e.g. “Rocket Launcher”The rocket launcher might in turn reference a 3dmodel indicating the visible appearance of theweapon when wieldedThe player could also reference the same weaponprototypeUsing this scheme, the code could treat theplayer’s weapon and the enemy’s weaponidenticallyThis buys consistency and reliability because weget code and interface re-use in-game

Mix n’ matchSub-prototypes can be further split into subsub prototypeszzGround movement prototype could be split into‘treads’ and ‘walking’, etc.This process can continue ad infinitumUsing prototypes with a component-basedarchitecture results in a flat object hierarchy,but a complex data hierarchy

What about Instances?Once you have your prototypes, you want tohave a way to create instances of them inyour game and set up the instance specificdataIn Smash TV 3D, different types of tokenswere handled differentlyzzzEnemies was created through spawn points. Atext file controlled the timing of enemy creation.The Spawn Points themselves were placed in thelevel in 3DS Max and were created when the levelstarted in the appropriate positionsPowerups were created randomly every couple ofseconds, based on a percentage in a text file

InstancesInstances can be created through designerintervention and/or through systemsThe creation must provide all of the instance specificdata that the token requiresThis is usually at least a position in the game worldIn Smash TV 3D, the spawn points gave each objectits initial position (at the spawn point)Initial velocity was always towards the center of theroomPowerups were created in a random position within acertain radius of the room’s center

Factory FunctionsA common way to implement instantiation oftokens is through factory functionsFactory functions take a prototype ID, and anyinstance-specific data that cannot be filled out bythe data source, and create an instance of anobjectUsually look something like:Some Type Of Object Handle Or PointerCreateObject(int PrototypeID, instance specific initial params.)Factory functions insulate concrete entity detailsfrom systems that use and spawn those entities

Prototype-instanceSummaryPrototypes consist of the informationnecessary to describe the basic traits of aspecific type of token in the gameThe instances of a prototype are the actualtokens of that type that exist in the gameworldInstances contain both a reference to theirprototype (ID) and instance-specific dataGame behavior is generated by tokens, theirprototypes, and the systems that operate onthose prototypes

Technique IV:ScriptingThe systems approach / componentarchitecture tends to break down when thenumber of unique prototypes of a given typebeings to grow dramatically, and when eachprototype requires very different behaviorExamples:zzScripted EventsObject AI implementation

Scripted Events / In-gameCutscenesYou want a specific sequence of events to occurredin a specific timed orderEach scripted event is uniqueHaving a system to manage a bunch of uniqueevents doesn’t make sense, since you just end upwith a lot of very special case functions in code, onefor each scripted event:void ();void id rldDomination();This makes it difficult to tweak these sequences

That bothersome AIObject AI is similar in this regardEach AI is unique and provides a different setof behaviorsMany of the behavioral variables need to begreatly tweaked before they look appropriateThere is not enough in common amongdisparate AIs to move all of their variables toa data source without enormous amounts ofeffort

The general problemYou will run into this problem whenever you’redealing with some component that requires alarge number of very different pieces of specialcase codeThe key word is ‘different’If you have a hundred different objects, but youcan break them down into a few variables andbehaviors, you can still use the system-prototypeapproachEach creature AI and cutscene has a vastlydifferent behavior, even in a simple game

Grunt Variablesstatic conststatic conststatic conststatic conststatic conststatic conststatic conststatic conststatic 2uint32uint32Rhino Boss Variablesstatic const uint32static const uint32static const uint32static const uint32static const uint32static const uint32static const uint32static const float32static const uint32kEnemyGruntBackswingSpeed 5.0f;kEnemyGruntSwingSpeed 15.0f;kEnemyGruntRecoverSpeed 2.0f;kEnemyGruntSpeed 15.0f;kEnemyGruntNumSwings 3;kEnemyGruntBackswingTime 300;kEnemyGruntSwingTime 100;kEnemyGruntRecoveringTime 500;kEnemyGruntRecoveredTime 200;kBossRhinoEntranceDuration 3000;kBossRhinoTurnTime 2000;kBossRhinoDeathTime 300;kBossRhinoTimeBetweenAttacks 5000;kBossRhinoTimeBetweenShots 100;kBossRhinoPrepShotTime 1000;kBossRhinoPrepChargeTime 3000;kBossRhinoChargeAdjust 0.95f;kBossRhinoChargeAdjustTime 250;and only a few variables in common:static const uint32static const uint32kBossRhinoHealth 500;kEnemyGruntHealth 1;

What do we want?Each custom behavior should be able tofunction in isolation from other custombehaviors, so it is easier to test and manageWe want to be able to tweak as easily aspossibleBehavior should be determined at run-time,rather than compile-time, for the abovereasonBehavior should be treated as “data”, ratherthan code, and be managed accordingly

Scripting LanguagesScripting languages are programminglanguage other than the one actually used toprogram your game, and are used them towrite game behavior through an APIYou pass the scripting language through toolsthat compile the language into a format thatcan be loaded on the fly and executed

Problems with ScriptingLanguagesWriting one is not for the faint of heartRequire an enormous amount of workYou have to write a compiler and executerYou have to expose an API to themYou will have to write a parameter marshallerYou will want a nice suite of tools, like a developmentenvironment, debugger, etc.There will be learning curve since it’s a brand new languageMay result in unmaintainable spaghetti code if poorly designedUsually at best 1/10 speed of C/C , so can drag downperformanceExisting scripting languages (Python, Ruby) may not meet yourneeds, there’s still a learning curve, and will still run very slowly

DllsAll we really want is to be able to write incode, and have that code loaded at run-timerather than linked in at compile-timeOn Windows, DLLs do exactly thatVery similar to executables – collections ofmethods and variables in a specific formatDLLs cannot be launched directlyAnother executable or DLL must load the DLLinto its memory space, and then it can usethe DLLs functions

Using DLLsYou should encapsule each different behaviorin its own DLLWithin each DLL, you’ll probably need toexpose a few entry pointszzzzA Run() methodAn Initialize() methodA Shutdown() methodA way to notify the script of eventsKeep entry points to a minimum; your gameshould communicate with the script in yourDLL through a limited number of connections

Using DLLs, 2You will need to provide an API to allow the script tocommunicate with the rest of the gameApproach 1:Write another DLL that contains the API. The game shouldload this DLL on startup and intialize it with access to all ofthe appropriate global variables. These variables shouldbe stored in a shared segment of the DLL. All script DLLsshould link against the LIB provided with this DLLApproach 2:When the script starts up, pass it a structure that contains abunch of function pointers to all of the API functions (oroptionally a class with pure virtual functions)

Using C classes in scriptsBecause of name-mangling, you can’t placethe exported functions in a classTo avoid this problem, you can use a wrapperapproach. In your initialize(), allocate aninstance of the class you want to use as aglobal variable. Then, have the Run(),CallEvent(), and other exported functions justforward the call to functions in the instantiatedclass.

A better approachCreate an abstract base class with the functions thatyou would have normally exposed in your DLL.class CScriptDLL{public:virtual bool Initialize() 0;virtual bool Shutdown() 0;virtual bool Run() 0;};You cannot instantiate CScriptDLL.You have to create a class that inherits from it, andimplement all its the pure virtual functions

class CCreatureAI: public CScriptDLL{public:virtual bool Initialize() {.}virtual bool Shutdown() {.}virtual bool Run() {.}};Now, any code that knows about CScriptDLL can callthese functions through a CScriptDLL pointer, even if itactually points to a CCreatureAI.Now, instead of exposing all of these functions in the DLL,you only need to expose one function:CScriptDLL* EXPORT CreateDLLInstance(){return new CCreatureAI;}When the executable loads your DLL, it only needs to callCreateDLLInstance(), hold on to the returned pointer, anduse it to call the Initialize(), Shutdown(), and Run() functions

Scripting Languages vs. DLLSThere are tradeoffs between both scripting languages andDLLsThe argument that scripting languages are easier to usefor non-programmers is irrelevant; most complex behaviorcan only be written by someone could also understandC/C One advantage scripting languages can offer is languagefeatures difficult or impossible to realize in C/ C For DLLs, you must have a version of Visual C or theequivalent on the machines that will be compiling scriptsFor a game like Quake, where a lively mod community isdesired, this may not be an optionOn consoles, you will have to learn the executable formatand write your own linker to use the DLL methodThis is still easier than writing a scripting language

Technique VI: The DataEditorThe prior techniques have suggestedways to move much of the gamebehavior into a ‘data source’ external tothe codeWe want to be able to edit the ‘datasource’ as easily as possibleA database can be a good choice foryour data source, since they are easy toread and edit

The Data Editor, 2Databases are only good for numerical and text dataFor graphical data, you should write new or leverageexisting tools to manipulate the data in a graphicalfashionTry to use existing tools when possibleIn Smash TV 3D, we used 3DS Max to create levelsand place spawn points, collision data, and doorsAt Outrage, we use Maya for editing of objects andlevels, and have written a whole suite of plugin tools toadd game contentEven for text and numerical data, it can also be usefulto write dialogs that wrap the database for ease ofediting

Technique VII: ASCII vs.BinaryIf you have a lot of files that get loaded into the game,you can adopt a dual ASCII / binary approachASCII is easier to debug and validateBinary is faster and reduces file sizeYou can have all your tools write out ASCII files in amanner that can be easily read inAlso provide a tool that convert the ASCII into tightlypacked binaryIf you add binary / ASCII transparency into your fileI/O libraries, you will get the best of both worldsDon’t read in the database as is either; have tools toconvert it to an easily-read binary form

Technique VIII:Reload game content on the flyEditing values in the database does notrequire a recompileIt still requires a restart of the game and areloadA system that lets you reload portions of thegame data while the game is actually runningcan save huge amounts of timeYou can even add a button on the data editorto automatically signal the game to reload itsgame data, making the process automatic

Technique IX: Debugglobal variablesDLLs / scripts often have dozens of variables that need tobe tweakedWe must recompile or at least reload the script to makeany changesThis slows down tweaking of these variablesIt is also far too time-consuming to expose all of thevariables in DLLs / scripts individually in the data sourceInstead, create some generic debug global variables(some floats, some ints, etc.)Use the debug variable in place of the real variable whiletesting values that need tweakingSince they are global, you can change their values in thedebuggerThis will give you instant feedback for tweaking

CaveatsDon’t lose sight of your original goalAll of these techniques require additionalwork up front before you see any resultsTake the timeframe and design of yourproject into accountDon’t write code that won’t be usedimmediatelyThe best way to design for the future is tohave a solid design and clean, wellcommented code

Data-driven designSummaryMoving game behavior out of code andinto data results in a more efficient processfor tweaking content and gameplayUse a component-based architecture with theprototype-instance approach for easilytweakable and incredibly flexible gametokensStructure your game systems to operate onspecific tokens and / or token components

Questions?

THE ENDTechniques and Strategies for DataDriven Design in Game DevelopmentScott ShumakerProgrammer,Outrage Gamessshumaker@outrage.com

Game development is hard From a technology standpoint, game development is no more difficult than other software development However, properly functioning technology is just one of many requirements for a successful title The majority of the development time is not spent developing technology, but content and gameplay.

Related Documents:

Bruksanvisning för bilstereo . Bruksanvisning for bilstereo . Instrukcja obsługi samochodowego odtwarzacza stereo . Operating Instructions for Car Stereo . 610-104 . SV . Bruksanvisning i original

10 tips och tricks för att lyckas med ert sap-projekt 20 SAPSANYTT 2/2015 De flesta projektledare känner säkert till Cobb’s paradox. Martin Cobb verkade som CIO för sekretariatet för Treasury Board of Canada 1995 då han ställde frågan

service i Norge och Finland drivs inom ramen för ett enskilt företag (NRK. 1 och Yleisradio), fin ns det i Sverige tre: Ett för tv (Sveriges Television , SVT ), ett för radio (Sveriges Radio , SR ) och ett för utbildnings program (Sveriges Utbildningsradio, UR, vilket till följd av sin begränsade storlek inte återfinns bland de 25 största

Hotell För hotell anges de tre klasserna A/B, C och D. Det betyder att den "normala" standarden C är acceptabel men att motiven för en högre standard är starka. Ljudklass C motsvarar de tidigare normkraven för hotell, ljudklass A/B motsvarar kraven för moderna hotell med hög standard och ljudklass D kan användas vid

LÄS NOGGRANT FÖLJANDE VILLKOR FÖR APPLE DEVELOPER PROGRAM LICENCE . Apple Developer Program License Agreement Syfte Du vill använda Apple-mjukvara (enligt definitionen nedan) för att utveckla en eller flera Applikationer (enligt definitionen nedan) för Apple-märkta produkter. . Applikationer som utvecklas för iOS-produkter, Apple .

This presentation and SAP's strategy and possible future developments are subject to change and may be changed by SAP at any time for any reason without notice. This document is 7 provided without a warranty of any kind, either express or implied, including but not limited to, the implied warranties of merchantability, fitness for a .

och krav. Maskinerna skriver ut upp till fyra tum breda etiketter med direkt termoteknik och termotransferteknik och är lämpliga för en lång rad användningsområden på vertikala marknader. TD-seriens professionella etikettskrivare för . skrivbordet. Brothers nya avancerade 4-tums etikettskrivare för skrivbordet är effektiva och enkla att

Den kanadensiska språkvetaren Jim Cummins har visat i sin forskning från år 1979 att det kan ta 1 till 3 år för att lära sig ett vardagsspråk och mellan 5 till 7 år för att behärska ett akademiskt språk.4 Han införde två begrepp för att beskriva elevernas språkliga kompetens: BI