검색결과 리스트
언어로그에 해당되는 글 48건
- 2015.09.03 [java] 글 목록
- 2015.08.30 [C/C++] C 언어 포스트 목록
- 2014.01.18 [프로젝트] Tweech (1)
- 2014.01.18 [프로젝트] 분실물 다나와 (1)
- 2014.01.18 [프로젝트] StarOS를 아시나요?
- 2013.02.16 [Java] 자바란?
- 2013.02.03 [java] 라이프 게임 (life game) (1)
- 2013.01.30 [java] 제13회 한국자바개발자 컨퍼런스
- 2012.03.11 HTML5 Canvas API
- 2011.10.15 jquery 간략한 사용법
글
[java] 글 목록
JAVA 5
- [Java] 자바란?
- [자바] (1) 자바소개
- 다형성
- 동시성
- 문자열
- 스윙의 기초
- 열거형
- 인터페이스
- 컨테이너
- 클래스 재사용, 상속과 위임
- 프로그램 실행제어
- Assertion
- Exception
- Files
- Graphics
- Inner Class(내부 클래스)
- package
- JCJP6.0
- Serialization
- 리플렉션으로 Getter 와 Setter 검사하기
- (1) 리플렉션(Reflection)
- (2) 리플렉션(Reflection) 사용하기
- 예외처리 (Exception Handling)
- [Java] 어노테이션 사용하기
- [Java] 어노테이션(Annotation)
비트 자바 고급과정
- 컬렉션(Collection)
- Hibernate, AOP
- MVC2, 리다이렉트, 포워드
- SQL
- SQL2
- 게시판 프로그램 변화 과정
- 네트워크, 소켓 프로그래밍
- 다국어 지원, 댓글구현
- 다운로드
- 스트러츠, iBATIS
- 아파치 프로젝트
- 웹서버 설계와 구현
- 이클립스 웹프로젝트 설정
- 자바 IO
- 자바 프로그래밍
- 페이징
- 프레임워크, 스트러츠, 4-layers
- 프레임워크 spring에 통합하기
- 프레임워크 spring에 통합하기. validation 프레임워크
- AJAX
- AjaxLib, DWR
- AspectJ, Tiles, SiteMash
- DWR로 로그인 하기
- EL, JSTL
- HTML1
- HTML2
- HTML3, Javascript
- IBATIS, 게시판, 댓글, 첨부파일, 회원결합
- IBATOR, 검색기능, IBATIS, Dynamic SQL
- JDBC
- JDBC2, SWING
- JDBC Template
- Junit, 단위테스트, 로그인 구현, Spring 프레임워크
- SAX, WAS
- Listener, Filter, AOP
- Servlet, JSP
- Spring과 IBATIS 연동, MultiActionController, SimpleFormController, DWR과 Spring 연동
- Spring 프레임워크, SpringMVC
- SpringMVC2, Spring2
- WAS 구현
- XML
라이프 게임(Life Game)
기타
'언어로그 > Java' 카테고리의 다른 글
| [java] 글 목록 (0) | 2015.09.03 |
|---|---|
| [Java] 자바란? (0) | 2013.02.16 |
| [java] 라이프 게임 (life game) (1) | 2013.02.03 |
| [java] 제13회 한국자바개발자 컨퍼런스 (0) | 2013.01.30 |
| Inner Class(내부 클래스) (0) | 2011.04.12 |
| 컬렉션(Collection) (0) | 2011.04.11 |
설정
트랙백
댓글
글
[C/C++] C 언어 포스트 목록
- C 언어란?
- C 프로그램 실행과정
- C 언어 학습에 핵심. 변수와 상수
- 음수의 표현
- 표준 입출력 함수 printf(), scanf()
- 비표준 입출력함수 getch(), getche()
- 매크로, 연산자
- 포인터의 이해
- 함수의 이해
- 전역변수와 지역변수
- 기억부류, 변수
- 배열의 이해
- 라인 입출력 함수
- 문자열 조작함수 직접 구현하기
- 과제 #1 입출력, 연산자
- 과제 #3 함수, 포인터의 사용
- 과제 #4 배열과 문자열
- 비트필드
- puchchar()
- scanf()
- 성적관리 프로그램
- 바이트 오더링
- 분할 컴파일
- 배열의 전달과 요소접근
- 구조체
- 전처리 지시어
- 파일 입출력
- 포인터 응용
'언어로그 > C/C++' 카테고리의 다른 글
| [C/C++] C 언어 포스트 목록 (0) | 2015.08.30 |
|---|---|
| 과제 #2 제어문/선택문을 이용해 다양한 모양그리기 (0) | 2011.06.13 |
| 과제 #1 입출력,연산자 (0) | 2011.06.13 |
| 음수의 표현 (0) | 2011.06.13 |
| 문자열 조작함수 직접 구현하기 (2) | 2011.04.29 |
| 라인 입출력 함수 (0) | 2011.03.27 |
설정
트랙백
댓글
글
[프로젝트] Tweech
1. 기본사항
시스템명: Tweech
주관기관: 앳게임
개발인원: 5명
프로젝트 기간: 2010.08.02 ~ 9.17
2. 프로젝트 소개
SNS 시장에서 트위터 서비스의 점유율이 빠른 속도로 증가함에 따라 트위터를 통한 정보와 지식 공유의 수준 역시 나날이 높아지고 있다.
Tweech 앱은 미국 내 트위터 서비스 이용자들을 대상층으로 한다. 단순한 키워드 검색 서비스를 넘어서서 사용자를 대변하는 Bot(로봇)을
Following 함으로써 관심있는 분야에 대한 최적의 글을 자신의 타임라인에서 구독할 수 있는 앱이다.
이런 검색시스템을 바탕으로 트위터 사용자들이 작성한 메시지들의 패턴을 분석하여 사용자와 유사한 유형을 가진 다른 사용자들을 추천해주는
기능을 제공한다. 트위터 검색시스템 구축을 1차 목표, 로봇 및 성향 분석 모듈 구축을 2차 목표로 하며, 현재 버전에서는 1차 목표까지 완료하였다.
3. 개발환경
타겟 시스템: iPhone 3GS
SDK: Java 5, iPhone SDK 3.0, Apache Lucene 3.0
언어: Java, Objective-C
프레임워크: iBATIS 2.3, Spring2.5, SpringMVC
분석/설계도구: Visual Paradigm
개발도구(IDE) : Eclipse 3.6, Xcode 3
서버 운영체제: CentOS 5.4
애플리케이션 서버: Apache Tomcat 6.02
데이터베이스: MySQL 5.1
[iPhone Client]
OAuth 인증처리 및 사용자 계정관리 (Objective-C / C언어 사용)
Third Party 라이브러리를 사용하지 않고, 웹 서비스 자원 오픈 표준인 OAuth 인증처리를
구현하였다. 최대 5개까지의 트위터 계정을 등록할 수 있으며, 최초 등록 시 OAuth 인증과정을
거치게 된다.
Tweeter API (Follow / Favorite / Retweet) 요청 및 처리 (Objective-C 언어 사용)
Tweeter API와 연동하여 검색된 트윗글을 북마크하고, 리트윗하는 기능을 구현하였다. 또한
트윗글 작성자를 팔로우하는 기능도 제공한다.
[Server]
색인기(Indexer) 모듈 (Java 언어 사용)
Apache Lucene 3.0 검색 라이브러리를 사용하여, 분석기를 구현하였다. Crawler 모듈에서 수집된 트윗글을 네트워크로 전송 받아 파일시스템에 색인파일을 생성한다.
[iPhone Client]
OAuth 인증처리 및 사용자 계정관리
OAuth 인증처리 과정은 다음과 같다. Tweeter API 지원 페이지에서 Third Party 앱으로
등록하면 Consumer Key, Consumer Secret 값이 발급된다. 이 값과 사용자부터 입력 받은
트위터 서비스 UserName과 Password를 바탕으로 OAuth 인증 URL로 접속하여 Request
Token 요청, Acces Token 요청과정을 거쳐 최종적으로 Access Token을 획득하게 된다.
Access Token은 사용자 데이터에 접근을 허용하는 일종의 허가권으로 인증이 요구되는 트위터
API 사용시 필요한 값이다. OAuth 구현시 트위터 OAuth 도움말 페이지 및 OAuth Core1.0 Spec을 참고하여 구현하였다.
최대 5개까지의 계정을 등록하여 사용할 수 있으며, 등록 요청을 받은 계정정보는 유효성 검사
후 OAuth 인증처리를 거치게 되며, 성공시 iPhone SQLite 데이터베이스에 저장된다.
6-2.색인기(Indexer) 모듈
색인기(Indexer) 모듈
색인기 모듈은 Java 언어를 사용하여, Apache Lucene 3.0 오픈소스 검색 라이브러리를 사용하여 구현하였다.
Crawler가 수집한 트윗글(Status) 목록을 네트워크를 통해 전송 받아, 색인파일을
생성하는 역할을 한다. Crawler가 수집한 트윗글 목록이 끊임없이 전송되기 때문에 지연없이
색인을 생성하는 것이 핵심이 된다. 색인속도가 전송되는 트윗글의 속도를 따라가지 못하게 되면 메모리 부족현상이 발생하게 된다.
성능을 향상을 위해 5개의 쓰레드로 동작하며, 100건 단위로 트윗글을 메모리에 색인한다. 빈번한 파일 색인 생성작업은 가장 CPU
자원을 소모하기 때문에 1000건의 트윗글이 메모리에 색인되면 파일색인을 생성하도록 처리하였다.
색인된 파일들은 NFS(Network File System)을 통해 검색기 모듈에 의해 참조된다.
빠른 검색을 지원하기 위해서 증가하는 색인파일들을 주기적으로 최적화하여 색인파일의 개수를
줄이고 정리해야한다. IndexerOptimizer는 색인기 모듈 구동과 동시에 지정된 시간 후에
일정 주기로 색인파일을 최적화 한다.
7. 주요화면
|
|
|
|
|
'언어로그 > 프로젝트로그' 카테고리의 다른 글
| [프로젝트] Tweech (1) | 2014.01.18 |
|---|---|
| [프로젝트] 분실물 다나와 (1) | 2014.01.18 |
| [프로젝트] StarOS를 아시나요? (0) | 2014.01.18 |
설정
트랙백
댓글
글
[프로젝트] 분실물 다나와
1.기본사항
시스템명:분실물 다나와
주관기관: 앳게임
개발인원: 5명
프로젝트 기간: 2010.10.1 ~ 11.19
2.프로제트 개요
매일 지하철에서만 약 200여건의 분실물이 발생하며 그 중 28% 가량이 주인에게 돌아가지 못하고 누적되어
보관장소 확충과 관리인력 낭비 문제를 발생시키고 있는 실정이다.
“분실물 다나와” 는 서울시 대중 교통 통합분실물 센터 웹서비스와 연동하여 사용자들이 분실물을 빠르게
찾을 수 있게 편리한 서비스 제공과 분실물 반환율 증가를 통한 예산 절감을 목표로 한다.
분실물 조회 서비스 이외에도 유사분실물로 의심되는 항목들을 Push 메시지로 전달해주는 편리한 기능을 제공한다.
또한 서울시 대중교통 조합에 소속된 모든 업체들의 연락처와 위치를 지도상에서 제공하여 좀더 용이하게 분실물을
회수할 수 있게한다. (서울시/중소기업청 주관 앱 공모전 출품)
3. 개발환경
타겟 시스템: iPhone 4G
SDK: Java 5, iPhone SDK 3.2
언어: Java, Objective-C
프레임워크: iBATIS 2.3, Spring2.5, SpringMVC
분석/설계도구: Visual Paradigm
개발도구(IDE) : Eclipse 3.6, Xcode 3.5
서버 운영체제: Ubuntu 10.04
애플리케이션 서버: Apache Tomcat 6.02
데이터베이스: PostgreSQL 8.4
4. 맡은 업무및 구현 내용
프로젝트 일정 계획 및 업무 분장
앱 화면전환 절차 설계
클라이언트/서버 유사 분실물 관리/통지 모듈 설계 및 구현
(Apple Push Notification Service 연동)
분실물 이미지 cache 모듈 설계 및 구현
5. 분실물 다나와 시스템 구성도
[iPhone Client]
클라이언트 유사 분실물 관리/통지 모듈
관심있는 분실물에 대한 대중교통, 분실물 종류를 입력하면 원하는 기간동안 분실물 센터에 등록되는 유사 분실물들의 정보를 Push 받을 수 있다. Push 서비스를 위해, 앱 최초 구동시 사용자
iPhone에 대한 Device Token과 UUID를 추출하여 서버에 전송하며, 이 값들은 APNS 에 Push를
요청하기 위해 필요한 데이터가 된다.
분실물 이미지 cache 모듈
웹서비스를 통해 검색된 분실물 목록을 10개 단위로 받아온다. 목록을 받아오는 API와 분실물에
대한 상세조회 API, 분실물 이미지 조회 API가 모두 분리되어 있어, 분실물 이미지를 조회하기
위해서는 3번의 요청이 이루어져야 한다. 다수의 요청과 동일한 이미지 중복요청으로 인한 성능
감소를 극복하기 위해 Dictionary에 요청한 이미지를 캐시하도록 구현하였다.
[Server]
서버 유사 분실물 통지 모듈
유사 분실물이 존재할 경우 Apple Push Notification Service 에 해당 사용자 앱에 Push 메시지전송을 요청한다. Local and Push Notification Programming Guide 문서를 참고하여 구현하였다.
6. 푸시 모듈 클래스 다이어그램
[APNS에 Push Service 등록 요청]
앱 최초 구동시 사용자 iPhone과 앱에 대한 Push 서비스 등록을 APNS 서버에 요청한다.
UIApplication 클래스에 registerForRemoteNotificationTypes: 메소드를 사용한다.
[APNS로부터 Device Token 수신]
서비스가 수락되면 APNS로부터 앱을 유일하게 식별하는 값인 Device Token을 응답 받는다.
APNS에 Push를 요청하기 위해 Device Token를 함께 전송해야 한다.
[서버에 Device Token과 UUID 전송]
사용자 Device를 유일하게 식별하기 위한 디바이스 UUID와 Push 요청을 위한 Device Token을
서버에 전송한다. UUID는 본 시스템에서 사용자를 유일하게 구분하는 값이 된다.
[서버에 통지 받을 분실물 등록]
사용자는 앱을 사용하여 관심있는 분실물에 대한 정보를 등록한다.
[Push 메시지 수신]
UIApplicationDelegate 프로토콜의 RemoteNotification 관련 메시지를 구현하면, Push 메시지를
통해 관심 분실물에 대한 키를 통지 받을 수 있게 된다.
[서버에 유사 분신물 목록 조회요청]
통지받은 키와 함께 유사 분실물 목록을 요청하면, XML 형태로 데이터를 수신받게 된다.
7. 주요 화면
메인화면
분실물 목록조회 화면
분실물 정보 상세조회
유사 분실물 발견시 등록
유사 분실물이 발견시 푸시수신
발견된 유사 분실물 목록
발견된 유사분실물 상세정보
대중교통별 분실물 센터의 전화번호와 위치 안내
버스별 분실물 센터
버스별 분실물센터 위치
'언어로그 > 프로젝트로그' 카테고리의 다른 글
| [프로젝트] Tweech (1) | 2014.01.18 |
|---|---|
| [프로젝트] 분실물 다나와 (1) | 2014.01.18 |
| [프로젝트] StarOS를 아시나요? (0) | 2014.01.18 |
설정
트랙백
댓글
글
[프로젝트] StarOS를 아시나요?
2009년 8월~12월은 가장 재미있었던 개발을 했던 순간으로 기억합니다.
비트 자바 고급반을 수강하면서 그동안 몰랐던 웹이라는 기술에 눈을 떳던 시간이었고,
프로젝트다운 프로젝트를 했던 순간이었고 좋은 동료들과 인상깊었던 결과물을 완성할 수 있었던 시간이었습니다.
결과물을 SourceForge 에 올려 오픈소스 프로젝트로 삼겠다던 당시의 포부는 게으름으로 이루지 못했지만 ^^;;
이대로 그냥 지나쳐 버리기엔 너무 아쉬울 당시의 결과물을 표현하고자 이 글을 작성합니다 ~
1. StarOS - "언제 어디서나 웹을 내 개인PC 환경처럼 쓸수 없을까"
StarOS는 웹을 마치 개인 PC 바탕화면처럼 사용하면 좋겠다는 생각으로 만들어진 "브라우저에서 동작하는 OS" 입니다.
현재의 서비스들에 비유하자면 "클라우드+웹하드+a" 정도로 생각할 수 있겠네요.
2. StarOS로 무엇을 할 수 있는데?
기획당시 일반적으로 개인 PC에서 할 수 있는 작업들을 할 수 있도록 하고 싶었습니다.
예를 들자면 음악/비디오 감상, 메일쓰기, 워드 문서작성, 사진 보기, 일정작성, 인터넷 서핑과 같은 가장 빈번하게
사용하는 작업들 말이죠.
2달이라는 짧은 시간동안 프로젝트를 완료 해야했기에 다소 기능을 제한하여 다음을 목표로 삼았습니다.
- 일반적인 윈도우 환경과 유사한 사용자 인터페이스를 제공한다
- 이미지 파일을 볼 수 있다.
- 음악과 비디오를 감상할 수 있다.
- 파워포인트, 워드문서를 볼 수 있다.
- 일정을 작성하고 조회할 수 있다.
- 개인파일을 업로드, 다운로드 할수 있다.
- 메일을 작성하고 조회할 수 있다.
프로젝트가 순조롭게 진행되었고, 2달이 다되어 갈 무렵에 계획했던 기능들이 모두 구현되었습니다.
팀원들과 테스트를 진행하던 중에, StarOS 가 기능들을 잘 제공하기는 하지만 너무 재미없다는 것을 깨닫게 되었습니다.
"누군가와 공유할 수 있는 무엇가가 있으면 좋겠다" 는 생각을 하게 되었고,
방문자에게 파일을 공개/비공개 유무를 설정할 수 있고, 방명록을 통해 글을 남길 수 있는 기능을 추가로 적용했습니다.
SNS 기능을 추가한 것인데요! 남아있는 프로젝트 시간이 없어서 "방명록" 과 "파일 공개설정" 에 그쳤지만
채팅이라던가 친구와 게임하기와 같은 소셜 기능 등 재미있는 요소를 많이 적용할 수 있겠다는 생각이 들었습니다.
3. 개발 개발 개발
4명의 팀원들과 주제선정, 마인드맵을 사용한 브레인스토밍을 거쳐 구현할 기능 구체화한 뒤...
업무를 분장하고 개발에 착수했습니다. Flex 플랫폼을 모두 처음 접했기 때문에 처음 진행은 더딜 수 밖에 없었습니다.
하지만 모두들 같은 목표를 위해 열심히 했고, 팀워크가 워낙 좋았기 때문에 조금씩 결과물이 보이기 시작했습니다.
제가 담당했던 부분은 전반적인 아키텍처 설계 및 탐색기와 메일클라이언트의 구현이었습니다.
"윈도우 창관리"와 "아이콘과 이벤트 연동" 과 같이 상당히 고난이도의 UI 를 다루는 기술이 필요했기에 처음에는 너무
막막했습니다. 그러던 중 구글코드에서 창관리를 구현한 오픈소스를 발견하였고, 저희 프로젝트에 맞게 커스터마이징하고
아이콘 배치구조와 클릭시 이벤트를 전송하는 구조를 구현하고, 팀원들에게 전파했습니다.
기반코드가 만들어지니 그 이후부터는 좀더 수월하게 진행할 수 있었습니다. 각 자 맡은 모듈을 구현하면서 재미있게 놀수 있었죠!
유일한 여자 팀원이 있었는데, 수업시간에 매일 조느라고 프로젝트에 적응할 수 있을까? 란 고민이 컸었는데 프로젝트에서
이분의 역할이 상당했습니다. 탁월한 디자인 안목으로 StarOS에 생명을 불어 넣어주셨었죠. 잠만 덜 자면 참 좋았을 텐데 ㅋ
4. 내가 StarOS다!
2달간의 프로젝트 완료후 발표회에서 사용했던 발표자료 입니다.
StarOS의 모습은 아래와 같습니다.
시연 영상도 볼까요?
전문 다자이너가 없어서 웹사이트 디자인은 많이 부실하지만
StarOS 애플리케이션은 나름 봐줄만 하죠 ^^
Java 고급과정에서 배웠던 Spring2.5, iBATIS 내용들을 200% 활용하였고, Flex도 학습할 수 있어서 기술적으로 많은 것을 배웠던 프로젝트였습니다.
가끔 그때 Source forge에 오픈소스로 등록하여 지금까지 계속 개선하고 가꾸어 왔으면 어땠을까? 하는 생각을 해보네요
마지막으로 "재미있게 개발을 하기위해 힘쓰고 있는가" 라는 물음을 던지면서 이 글을 마칠까 합니다.
'언어로그 > 프로젝트로그' 카테고리의 다른 글
| [프로젝트] Tweech (1) | 2014.01.18 |
|---|---|
| [프로젝트] 분실물 다나와 (1) | 2014.01.18 |
| [프로젝트] StarOS를 아시나요? (0) | 2014.01.18 |
설정
트랙백
댓글
글
[Java] 자바란?
벌써 4년전입니다. 2009년도에 비트 자바고급반을 수강하면서 학습한 내용을 Springnote에 꾸준히
정리했습니다. Springnote 서비스가 종료되고, 그 때 백업해 두었던 글들을 하나씩 티스토리로 옮기고
있는데... 열정과 흥미를 가지고 재미있게 공부했었던 그때 기억이 나네요.
2. 자바란?
자바 언어의 개발사인 썬은 spac 이란 서버제품군을 제작하는 회사였습니다.
낮은 H/W 마진을 개선하고자, 자사의 H/W 위에 마진이 높은 S/W(유닉스 등)를 얹혀서 팔려했는데
하드웨어마다 소프트웨어를 재작성해야 하는 문제가 있었습니다. 즉 다양한 머신 위에서
한번작성하면 동일하게 동작하는 S/W를 만들려는 노력해서 Java가 탄생하게 되었습니다
위키: http://en.wikipedia.org/wiki/Java_language
3. 자바의 장점
객체지향적, 플랫폼 독립적, 동적이고 배포하기 쉬우며... 견고하고 보안에 강하다!
하지만 객체지향적이고, 보안에 강하다는 특성을 살리는 것은 소프트웨어를 작성하는 개발자에 전적으로
달려있답니다. (무서운 강사님의 말씀...)
4. 플랫폼 독립적?
c언어는 컴파일러가 머신에 의존적인 기계어 코드(실행파일)를 생성합니다. 유닉스, 리눅스, 윈도우, 맥에서
실행하기 위해서는 소스 수준에서 재컴파일이 필요합니다.
자바는 OS와 소스코드 중간에 JVM(Java Virtual Machine)이라는 중간계층을 두어 이를 해결했습니다.
소스코드를 가산머신이 인식할 수 있는 중간언어인 바이트 코드로 컴파일해서 배포합니다. 그러면 각 OS에
설치되어 있는 JVM이 바이트 코드를 기계어로 번역하여 실행합니다.
(단, 각 OS 마다 각 머신에 맞는 JVM이 설치되어 있어야 합니다. 한번만 설치하면 되니까 매번 소스를
재컴파일해야 하는 것보다는 훨씬 유연성이 있죠)
5. 기업 인터넷 환경에서의 Java
유연성을 위해 3-Tier(프레젠테이션 계층-비지니스 계층-데이터(DB) 계층)의 형태로 구성됩니다.
현재는 더욱 확장된 N-Tier로 구성된다고 하네요.
PS. Three Tier를 삼-Tier로 읽는 센스 ㅋ
6. JVM 의 동작방식
클래스 로더가 소스코드를 스캔하여 모든 필요한 클래스를 로드합니다. 필요한 클래스 위치는 CLASSPATH
환경변수를 참조하게 찾게됩니다. JVM Verifier 가 오작동 될 수 있는 코드(무한루프와 같은...)를 검사해서
사전에 차단합니다. 이어서 바이트 코드를 실행하게 되는데, 이때 JIT(Just-In-Time) 컴파일러가 동작합니다.
즉 소스코드와 (컴파일된 .class)클래스 파일의 수정일자를 비교해서, 소스코드가 더 나중에 수정됐을 경우에만
재컴파일하게 됩니다.
(PS. JIT를 도입해서 자바의 느린 성능을 어느정도 극복했고, 버전업 될때마다 크게 향상되고 있습니다.
또 가비지 컬렉터라는 메모리 관리자가 더이상 사용되지 않는 객체를 수시로 검사하여 자동으로 메모리를
반환해줍니다)
7. 자바환경에서 보안 구현
언어차원과 컴파일러, 클래스 로더, 바이트코드 검증기(Verifier) 등 계층적으로 위해한 코드를 차단해줍니다.
8. 자바 애플리케이션의 배포방식
.zip 또는 .jar로 압축해서 배포합니다. .jar은 단순히 소스만 압축할 수도 있고, 클래스파일까지 함께 압축해서
실행가능한 형태로 만들 수 있습니다. 웹에서는 .war 형태로 압축해서 배포됩니다.
9. JDK(Java Development Kit)
통상 J2SE를 지칭합니다.컴파일러, 코어클래스 라이브러리, 디버거, JVM, JAR(Java ARchive utility) 등으로
구성됩니다. Java 1.2버전 이후부터 대폭 내부구조가 개선되었는데 이를 표현하기 위해 1.2버전 이후부터는
JAVA2라고 부릅니다. (웹2.0 처럼 큰 변화가 있었다는 의미이지요).
JAVA2에는 J2SE, J2ME, J2EE 이렇게 3가지가 있습니다.
J2ME는 모바일 환경의 S/W 작성을 위해 필요한 클래스만 추려낸 버전이고, J2EE는 기업환겨에 맞게 병렬실행
등을 강화한 버전입니다.
10. 자바빈즈(JavaBeans)
Beans는 땅콩을 의미하는 땅콩은 알맹이를 껍데이가 감싸는 형태로 되어있죠.
클래스가 속성과 메소드를 깜싸고 있는 모습이 흡사 땅콩과 같다해서 자바빈즈라고 부릅니다.
보통 프레임워크에서 데이터 속성과 표준화된 getter, setter를 갖는 클래스를 빈즈라고 합니다.
11. 기본형 데이터 타입
기본형 |
크기 |
Wrapper 클래스 |
비고 |
boolean |
16비트 |
Boolean |
true, false |
char |
8비트 |
Character |
유니코드 사용 |
byte |
8비트 |
Byte |
|
short |
16비트 |
Short |
|
int |
32비트 |
Integer |
|
long |
64비트 |
Long |
|
float |
32비트 |
Float |
|
double |
64비트 |
Double |
|
'언어로그 > Java' 카테고리의 다른 글
| [java] 글 목록 (0) | 2015.09.03 |
|---|---|
| [Java] 자바란? (0) | 2013.02.16 |
| [java] 라이프 게임 (life game) (1) | 2013.02.03 |
| [java] 제13회 한국자바개발자 컨퍼런스 (0) | 2013.01.30 |
| Inner Class(내부 클래스) (0) | 2011.04.12 |
| 컬렉션(Collection) (0) | 2011.04.11 |
설정
트랙백
댓글
글
[java] 라이프 게임 (life game)
스프링노트를 운영하던 시절 썼던 글인데 티스토리로 옮기면서 다시 읽어 보니 감회가 새롭네요
요즘엔 AWT/Swing 이 거의 쓰이지 않지만 이때 공부했던 GUI 프로그래밍이 이후에 플렉스와 아이폰을
공부하면서 GUI에 적응하는데 밑거름이 되었던 것 같네요!
1. 라이프 게임 개발을 시작하다
2008년 6월 25일 수요일 새벽 잠들기 전....
1년간 프로그래밍에 전혀 손 대지 않다가... 다시 프로그래밍을 하려고 하니 영~ 힘들다
1년이란 시간이 매우 길긴 기나부다...그 많은 것을 잊어버렸다. 자바 Spring 프레임워크를 파보려고 하는데
읽어도 무슨말인지 모르겠고, 이클립스 등 개발환경 셋팅하는데만 하루가 걸렸다. ㅡㅡ;;
잊어버린 자바 관련 지식을 상기시키고자, 첫 번째 프로젝트에 들어갔다. 프로그램은 "콘웨이"에 '라이프 게임!'
게임 알고리즘이 간단해서 연습용 프로젝트에 딱인 것 같다.
그럼 라이프 게임이 무엇인지부터 알아보자!
2. 라이프 게임이란?
라이프 게임(Game of Life) 또는 생명 게임은 영국의 수학자 존 호튼 콘웨이가 고안해낸 세포 자동자의
일종으로, 가장 널리 알려진 세포 자동자 가운데 하나이다. 미국의 과학잡지 사이언티픽 어메리칸 1970년
10월호 중 마틴 가드너의 칼럼 〈Mathematical Games(수학 게임)란을 통해 처음으로 대중들에게 소개되어
단순한 규칙 몇가지로 복잡한 패턴을 만들어낼 수 있다는 점 때문에 많은 관심과 반응을 불러일으켰다.
설명
이 ‘게임’은 사실 게임을 하는 사람이 자신의 의지로 게임의 진행을 결정하는 일반적인 게임과는 다르다.
라이프 게임의 진행은 처음 입력된 초기값만으로 완전히 결정된다.
라이프 게임은 무한히 많은 사각형(혹은 ‘세포’)로 이루어진 격자 위에서 돌아간다. 각각의 세포 주위에는
인접해 있는 여덟 개의 ‘이웃 세포’가 있으며, 또 각 세포는 ‘죽어’ 있거나 ‘살아’ 있는 두가지 상태중
한가지 상태를 갖는다. 격자를 이루는 세포의 상태는 연속적이 아니라 이산적으로 변화한다. 즉, 현재 세대의
세포들 전체의 상태가 다음 세대의 세포 전체의 상태를 결정한다.
...
패턴의 예
라이프 게임에는 전혀 변화가 없는 고정된 패턴(정물 靜物, still life), 일정한 행동을 주기적으로 반복하는 패턴
(진동자, oscillator), 한쪽 방향으로 계속 전진하는 패턴(우주선, spaceship) 등 여러 패턴이 존재한다.
‘block’과 ‘boat’는 정물이고, ‘blinker’와 ‘toad’는 진동자, 그리고 ‘글라이더(glider)’와 ‘경량급 우주선(lightweight spaceship — LWSS)’은 우주선에 속한다...
출처 Wikipedia
3. 게임 규칙
게임규칙을 요약하면 아래와 같다
* 셀의 상,하,좌,우,각 대각선 8개의 인접한 셀을 이웃으로 한다.
* 셀은 세대를 거듭하며 살거나 죽는다.
1. 정확히 3개의 이웃이 살아있다면, (죽어있는) 셀이 살아난다.
2. 2개의 이웃이 살아있다면 살아있는 셀은 다음세대에도 살아남든다
3. 1개 이하 또는 4개 이상의 이웃이 살아있다면, 살아있는 셀은 외로워서 또는 질식해서 죽는다.
4. 구현하기
프로그래밍을 하기 위하여 구현한 절차는 아래와 같다.
먼저 모든 셀들을 순회하면서 살아있는 이웃셀을 카운트하고, 살아있는 이웃의 개수를 저장한다
이를 바탕으로 위 세가지 규칙을 적용하여 다음세대 살아있는 셀들을 결정한다.
간략하게 만들어 화면은 아래와 같다.
4.1 게임판의 표현
게임판은 JPanel을 상속하는 Cell을 가로, 세로 size 개수 만큼의 요소로 갖는 이차원 배열로 표현하였다.
LifeGame 클래스는 게임의 전체적인 흐름을 관리하는 메소드들을 갖는다.
public class LifeGame extends JPanel {
...
private void init() {
setLayout(new GridLayout(size,size));
cells = new Cell[size][size];
for (int i=0; i < size; i++)
for (int j=0; j < size; j++) {
cells[i][j] = new Cell();
cells[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(cells[i][j]);
}
rule = new GameRule(cells);
}
...
public void transition() {
rule.countAliveNeibor();
rule.applyRule();
}
...
}
4.2 셀의 표현과 셀의 상태
Cell은 live 상태(true이면 살아있고, false 죽어있는 상태)와 살아있는 이웃의 개수에 대한 변수를 갖는다.
live 상태에서 따라서 셀이 그려지거나 혹은 그려지지 않거나 한다.
public class Cell extends JPanel {
private boolean live = false;
private int neighborCount = 0;
private Image img = null;
private int w, h;
...
@Override
protected void paintComponent(Graphics g) {
...
if (live) {
gg.drawImage(img, 0, 0, this);
}
else {
gg.setColor(getBackground());
gg.fillRect(0, 0, getWidth(), getHeight());
}
g.drawImage(image, 0, 0, this);
}
}
4.3 게임규칙의 표현
턴마다 LifeGame 클래스의 transition()메소드가 호출되면, GameRule 클래스의 countAliveNeibor() 메소드가
먼저 호출되고, 이웃하는 셀들에 개수를 모두 카운팅 한뒤, 살아있는 세대를 결정하기 위해 applyRule()메소드가 호출된다.
public class GameRule {
...
public void countAliveNeibor() {
...
}
public void applyRule() {
int neighborCount;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
neighborCount = cells[r][c].getNeighborCount();
if (cells[r][c].getLife()) {
if (neighborCount <= 1 || neighborCount >= 4)
cells[r][c].setLife(false);
}
else {
if (neighborCount == 3)
cells[r][c].setLife(true);
}
}
} //for
}
}
5. 버려진 프로그램은 싫다! 리팩토링~
2009년 08월 04일
예전에 만든 라이프게임 UI가 허접해서 라이프게임 알고리즘은 그대로 드고, 드로잉부분만 수정해서 다시 만들어봤다.
기존에는 메인패널 하나에 좌표를 가지고 Graphics 객체의 드로잉 메소드로 그렸지만, 이번에는
셀하나가 JPanel을 상속하게 했고, 셀이 살아있으면, 이미지를 로딩해서 그리게 했다.
빠른 드로잉을 위해 역시 더블 버퍼링을 사용한다
Timer로는 javax.util.Timer를 사용했다.
TimerTask 쓰레드를 정의해서, 2초마다 상태전이(transition) 후 드로잉하도록 했다.
pauser 기능은 wait() / notify() 를 사용해서, TimerTask 쓰레드를 wait()로 대기상태로 만들고
notifyAll()로 다시 깨우도록 처리했다.
6. 개발하게 하면서 이런걸 알게되었다~
1. AWT의 컴포넌트(Canvas)와 Swing의 컴포넌트(JMenu)를 함께 사용하면, Canvas에 가려 메뉴가 안보인다
중량컨테이너(High Weight Container)인 AWT 와 경량컨테이너(Light Weight Container)인 Swing을 함께
사용해서 그렇다고 한다. 따라서 중량 컨테이너와 중량 컨테이너를 함께 사용하지 말아야 한다.
Swing에서는 Canvas대신 Panel을 사용한다
2. Javax.swing.Timer 객체를 통해 타이머를 구현할 수 있다.
Javax.swing.Timer timer = new Timer(int timeoutMil, ActionListener listener);
3 . 더블버퍼링
Image buffer = Component.createImage(int width, int height); 컴포넌트에 버퍼를 얻고,
Graphics g = buffer.getGraphics(); 그래픽스 객체 g에 드로잉한다
Componet.getGraphics().drawImage(buffer, posintX, positionY, Componet); 버퍼를 컴포넌트에 덮는다
4. 이차원 배열의 사용
Cell을 표현하는 이차원 배열의 생성은 다음과 같다
Cell[][] cell = new Cell[size][size];
for (int i=0; i < size; i++)
for (int j=0; j < size; j++)
cell[i][j] = new Cell();
주의할 점은 Cell 타입의 이차원배열을 생성하고, 그 이차원 배열을 순회하며 실제로 각 배열의 원소에 Cell 객체를
생성하고 할당해야 한다는 것!
7. 만들면서 삽질하게 만든 요인들
첫째로,
타이머 이벤트 발생할 때마다, JPanel 클래스를 상속한 MyPanel에서 public void paint(Graphics g)
메소드를 오버라이드 했는데, 해당좌표에 셀이 도무지 제대로 그려지지 않았다 --^;
갖은 실수 끝에 실수로 알고리즘 메소드가 주석처리 되었었다는 사실을 깨닫고 수정했다. otz...
둘째로,
이전 라이프셀이 지워지지 않는채, 계속 덮입혀져 그려진다. 이것은 더블버퍼링을 이용해서 해결!
생각보다 자바의 드로잉은 속도가 느려서 더블버퍼링을 사용하지 않으면, 화면갱신이 드로잉을 따라가지
못하는 것 같다.
셋째로,
AWT에서의 Canvas 대신, Swing에서는 JPanel을 사용하는데, 드로잉을 하는데 있어서 잘 생각해야 한다.
프로그램이 시작되자 마자 JPanel에 무엇이 그려져야 한다면, 더더욱 그렇다. 게임이 시작하자마자 셀라인을
보이게 하려고 했다. JFrame의 생성자에 그리는 코드를 넣을게 아니라, public void paint(Graphics g) 메소드에서
처리하면 해결할 수 있다. 이때 그리는데 필요한 데이터값이 정확히 대입이 됐는지 잘 살펴야, 삽질을 피할수 있다.
어쨌든 이래저래 해서, 몸풀기 자바 프로그램을 완성했다. 요거 하면서 그나마 잊어버렸던 자바 지식들을 조금씩
기억하게 되어 도움이 되었다.
8. 짜잔~ 최종적으로 만들어진 프로그램
소스 다운로드
다음은 LifeGame, GameRule, Cell 클래스 소스이다.
package lifegame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class LifeGame extends JPanel {
private Cell[][] cells;
private int size;
private GameRule rule;
public LifeGame(int size) {
this.size = size;
init();
}
// 초기화
private void init() {
setLayout(new GridLayout(size,size));
cells = new Cell[size][size];
for (int i=0; i < size; i++)
for (int j=0; j < size; j++) {
cells[i][j] = new Cell();
cells[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(cells[i][j]);
}
rule = new GameRule(cells);
}
public void cellAlive(int r, int c) {
cells[r][c].setLife(true);
}
public void cellDead(int r, int c) {
cells[r][c].setLife(false);
}
public boolean getLifeCell(int r, int c) {
return cells[r][c].getLife();
}
public void clearGame() {
for (Cell[] cs : cells)
for (Cell c : cs)
c.setLife(false);
}
public void transition() {
rule.countAliveNeibor();
rule.applyRule();
}
@Override
protected void paintComponent(Graphics g) {
for (Cell[] cs : cells)
for (Cell c : cs)
c.repaint();
}
}
package lifegame;
public class GameRule {
private Cell[][] cells;
private static final int LEFT = -1, UP = -1;
private static final int RIGHT = 1, DOWN = 1;
private int rows, cols;
public GameRule(Cell[][] cells) {
this.cells = cells;
rows = cells.length;
cols = cells[0].length;
}
// 각 셀의 살아있는 이웃을 센다
public void countAliveNeibor() {
int nNeighbor;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
nNeighbor = 0;
if (r + UP >= 0)
if(cells[r + UP][c].getLife())
nNeighbor++;
if (r + UP >= 0 && c + RIGHT < cols)
if (cells[r + UP][c + RIGHT].getLife())
nNeighbor++;
if (c + RIGHT < cols)
if (cells[r][c + RIGHT].getLife())
nNeighbor++;
if (r + DOWN < rows && c + RIGHT < cols)
if (cells[r + DOWN][c + RIGHT].getLife())
nNeighbor++;
if (r + DOWN < rows)
if (cells[r + DOWN][c].getLife())
nNeighbor++;
if (r + DOWN < rows && c + LEFT >= 0)
if (cells[r + DOWN][c + LEFT].getLife())
nNeighbor++;
if (c + LEFT >= 0)
if (cells[r][c + LEFT].getLife())
nNeighbor++;
if (r + UP >= 0 && c + LEFT >= 0)
if (cells[r + UP][c + LEFT].getLife())
nNeighbor++;
cells[r][c].setNeighborCount(nNeighbor);
}
} // for
}
// 살아있는 셀은 이웃이 1명 이하, 4명 이상이면 죽는다
// 죽어있는 셀은 이웃이 3명이면 살아난다
// 이웃이 2,3명인 살아있는 셀은 계속 산다
public void applyRule() {
int neighborCount;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
neighborCount = cells[r][c].getNeighborCount();
if (cells[r][c].getLife()) {
if (neighborCount <= 1 || neighborCount >= 4)
cells[r][c].setLife(false);
}
else {
if (neighborCount == 3)
cells[r][c].setLife(true);
}
}
} //for
}
}
package lifegame;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.io.BufferedInputStream;
import javax.swing.JPanel;
import javax.imageio.ImageIO;
@SuppressWarnings("serial")
public class Cell extends JPanel {
private boolean live = false;
private int neighborCount = 0;
private Image img = null;
private int w, h;
public Cell() {
try {
img = ImageIO.read(new BufferedInputStream(Res.class.getResourceAsStream("../life.png")));
w = img.getWidth(this);
h = img.getHeight(this);
setPreferredSize(new Dimension(w,h));
} catch (Exception e) {
e.printStackTrace();
}
}
public void setLife(boolean s) {
live = s;
}
public boolean getLife() {
return live;
}
public void setNeighborCount(int n) {
neighborCount = n;
}
public int getNeighborCount() {
return neighborCount;
}
@Override
protected void paintComponent(Graphics g) {
// 더블 버퍼링
Image image = createImage(getWidth(), getHeight());
Graphics gg = image.getGraphics();
if (live) {
gg.drawImage(img, 0, 0, this);
}
else {
gg.setColor(getBackground());
gg.fillRect(0, 0, getWidth(), getHeight());
}
g.drawImage(image, 0, 0, this);
}
}
'언어로그 > Java' 카테고리의 다른 글
| [java] 글 목록 (0) | 2015.09.03 |
|---|---|
| [Java] 자바란? (0) | 2013.02.16 |
| [java] 라이프 게임 (life game) (1) | 2013.02.03 |
| [java] 제13회 한국자바개발자 컨퍼런스 (0) | 2013.01.30 |
| Inner Class(내부 클래스) (0) | 2011.04.12 |
| 컬렉션(Collection) (0) | 2011.04.11 |
설정
트랙백
댓글
글
[java] 제13회 한국자바개발자 컨퍼런스
올해도 어김없이 코엑스 그랜드볼룸에서 열리는 한국개발자 컨퍼런스 !
2011년 난생 처음 JCO를 방문하고 두근거렸던 설렘이 엊그제 같은데
어느덧 2년이라는 시간이 흘렀네요ㅜㅠ
아이폰 개발을 하면서 자바에는 소홀해졌었는데...이번 JCO를 기점으로 다시한번
자바에 대한 열정을 불태워야겠습니다!!
11회 때 축하공연을 한 달샤벳도 굉장히 인상적이었는데, 12회때는 축하공연이 없어서
살짝 아쉬웠다는... ㅎㅎ
유익하고 개발자들의 탐구욕을 자극시켜줄 한국 자바 개발자 컨퍼런스를 기대해 봅니다.
보너스로 ... 11회때 공연마치고 차량으로 복귀하는데 "이쪽 좀 봐주세요!" 하는 외침에
난감한 표정으로 답하는 세리양 이네요 ㅎ
'언어로그 > Java' 카테고리의 다른 글
| [Java] 자바란? (0) | 2013.02.16 |
|---|---|
| [java] 라이프 게임 (life game) (1) | 2013.02.03 |
| [java] 제13회 한국자바개발자 컨퍼런스 (0) | 2013.01.30 |
| Inner Class(내부 클래스) (0) | 2011.04.12 |
| 컬렉션(Collection) (0) | 2011.04.11 |
| 리플렉션으로 Getter 와 Setter 검사하기 (0) | 2011.04.07 |
설정
트랙백
댓글
글
HTML5 Canvas API
// canvas template
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// draw line
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.moveTo(100, 150);
context.lineTo(450, 50);
context.lineWidth = 15;
context.strokeStyle = "#ff0000"; // line color
context.stroke();
// draw arc
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 75;
var startingAngle = 1.1 * Math.PI;
var endingAngle = 1.9 * Math.PI;
var counterclockwise = false;
context.arc(centerX, centerY, radius, startingAngle, endingAngle, counterclockwise);
context.lineWidth = 15;
context.strokeStyle = "black"; // line color
context.stroke();
// draw curve
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var controlX = 288;
var controlY = 0;
var endX = 388;
var endY = 150;
context.moveTo(188, 150);
context.quadraticCurveTo(controlX, controlY, endX, endY);
context.lineWidth = 10;
context.strokeStyle = "black"; // line color
context.stroke();
// draw bezier
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var controlX1 = 140;
var controlY1 = 10;
var controlX2 = 388;
var controlY2 = 10;
var endX = 388;
var endY = 170;
context.moveTo(188, 130);
context.bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endX, endY);
context.lineWidth = 10;
context.strokeStyle = "black"; // line color
context.stroke();
// draw path
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.beginPath();
context.moveTo(100, 20);
context.lineTo(200, 160); // line 1
context.quadraticCurveTo(230, 200, 250, 120); // quadratic curve
context.bezierCurveTo(290, -40, 300, 200, 400, 150); // bezier curve
context.lineTo(500, 90); // line 2
context.lineWidth = 5;
context.strokeStyle = "#0000ff";
context.stroke();
// draw rectangle
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var topLeftCornerX = 188;
var topLeftCornerY = 50;
var width = 200;
var height = 100;
context.beginPath();
context.rect(topLeftCornerX, topLeftCornerY, width, height);
context.fillStyle = "#8ED6FF";
context.fill();
context.lineWidth = 5;
context.strokeStyle = "black";
context.stroke();
// draw pattern
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function(){
var pattern = context.createPattern(imageObj, "repeat");
context.rect(10, 10, canvas.width - 20, canvas.height - 20);
context.fillStyle = pattern;
context.fill();
};
imageObj.src = "wood-pattern.png";
// draw image
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var destX = 69;
var destY = 50;
var imageObj = new Image();
imageObj.onload = function(){
context.drawImage(imageObj, destX, destY);
};
imageObj.src = "darth-vader.jpg";
// draw text
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var x = 150;
var y = 100;
context.font = "40pt Calibri";
context.fillStyle = "#0000ff"; // text color
context.fillText("Hello World!", x, y);
// draw shadow
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.rect(188, 40, 200, 100);
context.fillStyle = "#8ED6FF";
context.shadowColor = "#bbbbbb";
context.shadowBlur = 20;
context.shadowOffsetX = 15;
context.shadowOffsetY = 15;
context.fill();
// clear canvas
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.rect(188, 40, 200, 100);
context.fillStyle = "#8ED6FF";
context.shadowColor = "#bbbbbb";
context.shadowBlur = 20;
context.shadowOffsetX = 15;
context.shadowOffsetY = 15;
context.fill();
// animation
window.requestAnimFrame = (function(callback){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
};
})();
function animate(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// update
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// draw
// request new frame
requestAnimFrame(function(){
animate();
});
}
window.onload = function(){
// initialize stage
animate();
};
// linear motion
window.requestAnimFrame = (function(callback){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
};
})();
function animate(lastTime, myRectangle){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// update
var date = new Date();
var time = date.getTime();
var timeDiff = time - lastTime;
var linearSpeed = 100; // pixels / second
var linearDistEachFrame = linearSpeed * timeDiff / 1000;
var currentX = myRectangle.x;
if (currentX < canvas.width - myRectangle.width - myRectangle.borderWidth / 2) {
var newX = currentX + linearDistEachFrame;
myRectangle.x = newX;
}
lastTime = time;
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// draw
context.beginPath();
context.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);
context.fillStyle = "#8ED6FF";
context.fill();
context.lineWidth = myRectangle.borderWidth;
context.strokeStyle = "black";
context.stroke();
// request new frame
requestAnimFrame(function(){
animate(lastTime, myRectangle);
});
}
window.onload = function(){
var myRectangle = {
x: 0,
y: 50,
width: 100,
height: 50,
borderWidth: 5
};
var date = new Date();
var time = date.getTime();
animate(time, myRectangle);
};
// animation start & stop
window.requestAnimFrame = (function(callback){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
};
})();
function drawRect(myRectangle){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.beginPath();
context.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);
context.fillStyle = "#8ED6FF";
context.fill();
context.lineWidth = myRectangle.borderWidth;
context.strokeStyle = "black";
context.stroke();
}
function animate(lastTime, myRectangle, animProp){
if (animProp.animate) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// update
var date = new Date();
var time = date.getTime();
var timeDiff = time - lastTime;
var linearSpeed = 100;
// pixels / second
var linearDistEachFrame = linearSpeed * timeDiff / 1000;
var currentX = myRectangle.x;
if (currentX < canvas.width - myRectangle.width - myRectangle.borderWidth / 2) {
var newX = currentX + linearDistEachFrame;
myRectangle.x = newX;
}
lastTime = time;
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// draw
drawRect(myRectangle);
// request new frame
requestAnimFrame(function(){
animate(lastTime, myRectangle, animProp);
});
}
}
window.onload = function(){
var myRectangle = {
x: 0,
y: 50,
width: 100,
height: 50,
borderWidth: 5
};
/*
* make the animation properties an object
* so that it can be modified by reference
* from an event
*/
var animProp = {
animate: false
};
// add click listener to canvas
document.getElementById("myCanvas").addEventListener("click", function(){
if (animProp.animate) {
animProp.animate = false;
}
else {
animProp.animate = true;
var date = new Date();
var time = date.getTime();
animate(time, myRectangle, animProp);
}
});
drawRect(myRectangle);
};
// mouse position
function writeMessage(canvas, message){
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
function getMousePos(canvas, evt){
// get canvas position
var obj = canvas;
var top = 0;
var left = 0;
while (obj && obj.tagName != 'BODY') {
top += obj.offsetTop;
left += obj.offsetLeft;
obj = obj.offsetParent;
}
// return relative mouse position
var mouseX = evt.clientX - left + window.pageXOffset;
var mouseY = evt.clientY - top + window.pageYOffset;
return {
x: mouseX,
y: mouseY
};
}
window.onload = function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
canvas.addEventListener('mousemove', function(evt){
var mousePos = getMousePos(canvas, evt);
var message = "Mouse position: " + mousePos.x + "," + mousePos.y;
writeMessage(canvas, message);
}, false);
};
'언어로그 > Html/Javascript/CSS' 카테고리의 다른 글
| HTML5 Canvas API (0) | 2012.03.11 |
|---|---|
| jquery 간략한 사용법 (0) | 2011.10.15 |
| [HTML5] 데이터 스토리지 (0) | 2011.06.26 |
| HTML 소개 (0) | 2011.06.13 |
설정
트랙백
댓글
글
jquery 간략한 사용법
html5 변경사항
DOCTYPE 과 meta 태그가 간소화
<!DOCTYPE html>
<meta charset=utf-8>
자바스크립트 배치하는 습관
자바스크립트를 head 영역에 두면, 모든 자바스크립트 코드를 로드하기 전까지 도큐먼트 컨텐츠를 로드하지 못함.
가능한 자바스크립트 코드를 아래에 위치시키는 것이 컨텐츠 퍼포먼스를 위해 좋음.
페이지가 준비된 후 자바스크립트 코드 실행
페이지 로드가 완료된후 자바스크립트 코드를 실행하기 위해 다음과 같이 jQuery 를 사용함.
$(function(){
// code
$ 기호는 jQuery 의 축약표시
$(something) 은 실제로 jQuery(something) 이며,
$(function_callback) 는 ready 이벤트에 대한 또다른 축약표현이다.
다음과 동일하다.
$(document).ready(function_callback);
jQuery(document).ready(function_callbak);
JQuery
DOM 엘리먼트를 쉽게 네비게이팅 할수 있도록 설계된 자바스크립트 라이브러리
엘리먼트 조작, 이벤트 처리, 비동기 리모트 콜을 생성할 수 있음.
2개의 주요부분을 포함함. 선택자와 변경자. 선택자는 웹페이지 내 일치된 모든 엘리먼트를 선택하기 위해
CSS 셀렉터 문법을 사용함. 변경자는 선택된 엘리먼트에 자식을 추가, 삭제, 스타일을 변경함. jQuery를 사용한다는 것은
선택과 수정을 연속적으로 수행함을 의미한다.
jQuery 선택자
jQuery CSS 함수
css는 선택된 엘리먼트의 css 속성을 얻어오고, 설정하는 함수임.
jQuery 사용의 장점
DOM 노드를 선택하고 수정하는 코드량을 줄임.
더 짧은 코드로 가독성을 높임
개발 스피드를 증가시킴
크로스브라우저 처리를 대신해줌
absolute position 이해하기
abosolute position 이 설정되면, left, top 속성은 좌표로 다루어짐. 양의 y좌표는 아래방임.
디폴트로 let, top속성은 웹페이지의 top, left 가장자리를 가리킨다. 이 기준 좌표는 DOM 노드가 어떤 postion 속성을
설정하느냐에 따라 달라진다. left, top 속성의 기준점은 그 부모의 top left 가장자리가 된다.
html5 계층구조
html5 게임개발시에는 종종 html 계층를 잘 구조화하는 것부터 시작한다.
html 계층구조는 유사한 게임 객체들을 그룹핑하는데, Adobe Flash 에서 무비클릭과 유사하다.
그룹핑된 게임 객체들을 일종의 레이어로 간주하면 쉽게 스타일을 적용할 수 있다.
키보드의 키가 눌려졌는지 알아내기
키보드의 모든 키에는 키번호가 할당되어 있으며, 이 번호를 조회해서 키보드가 눌려졌는지 여부를 검사할 수 있다.
jQuery 의 keydown 이벤트 리스너를 통해 이벤트를 감시하고, event 발생시 event 객체는 key code 속성을 포함하고 있다.
event 객체의 which 함수를 호출하여 키 코드를 획득할 수 있다.
문자열을 숫자로 변환
$("#paddleA").css("top") 은 100이 아닌 문자열 "100px"을 반환함.
parseInt(string, radix) 을 사용하여 명시적으로 숫자로 변환시켜주어야 4칙 연산을 할 수 있음.
jQuery 함수 html()
선택된 엘리먼트의 컨텐츠를 얻어오고, 수정함.
.html() : 처음으로 일치되는 엘리먼트의 html 컨텐츠를 반환
.html(htmlString) : 모든 일치하는 엘리먼트의 html 컨텐츠를 설정함.
'언어로그 > Html/Javascript/CSS' 카테고리의 다른 글
| HTML5 Canvas API (0) | 2012.03.11 |
|---|---|
| jquery 간략한 사용법 (0) | 2011.10.15 |
| [HTML5] 데이터 스토리지 (0) | 2011.06.26 |
| HTML 소개 (0) | 2011.06.13 |
JDK_000_LifeGame.zip